如果文件是在“a+b”中打开的,fseek() 是否将文件指针移动到文件的开头?模式?

发布于 2024-10-28 22:57:26 字数 944 浏览 5 评论 0原文

我希望使用“a+b”模式打开一个文件,即如果它不存在,则会自动创建,但如果存在,我不想覆盖它。我希望能够读取和写入该文件。

该文件是二进制的,我想在其中保存特定struct的记录。所以我想对我想要的记录执行fseek(),然后使用fwrite()保存记录。

代码如下所示(MyRecordstructtypedef,而 FILENAME#定义到文件名):

int saveRecord(MyRecord *pRecord, int pos)
{
    FILE* file = fopen(FILENAME, "a+b");
    if (file == NULL)
    {
        printf("Unable to open file %s\n", FILENAME);
        return 0;
    }

    fseek(file, pos * sizeof(MyRecord), SEEK_SET);
    fwrite(pRecord, sizeof(MyRecord), 1, file);
    fclose(file);
    return 1;
}

但是,即使我将 pos 设置为 0,此代码也只是将记录附加到文件末尾。为什么不是 fseek()SEEK_SET 在附加模式下工作?

我知道我可以简单地用“r+b”打开它,如果失败,用“wb”打开它,但我想知道为什么这不起作用以及为什么 fseek()SEEK_SET 将文件指针保留在末尾。任何对记录此行为的地方的引用表示赞赏(因为我找不到任何内容,或者我使用了错误的关键字)。

I wish to open a file using the "a+b" mode, i.e. if it does not exist it is created automatically, but if it does I don't want to overwrite it. I want to be able to read and write to the file.

The file is binary, and I want to save records of a specific struct in it. So I want to do fseek() to the record I want and then save the record using fwrite().

The code looks as follows (MyRecord is a typedef to a struct, while FILENAME is a #define to the file's name):

int saveRecord(MyRecord *pRecord, int pos)
{
    FILE* file = fopen(FILENAME, "a+b");
    if (file == NULL)
    {
        printf("Unable to open file %s\n", FILENAME);
        return 0;
    }

    fseek(file, pos * sizeof(MyRecord), SEEK_SET);
    fwrite(pRecord, sizeof(MyRecord), 1, file);
    fclose(file);
    return 1;
}

However this code just appends the record to the end of the file, even if I set pos to 0. Why isn't fseek() with SEEK_SET working in append mode?

I know I can simply open it with "r+b" and if it fails open it with "wb", but I want to know why this doesn't work and why fseek() with SEEK_SET is leaving the file pointer at the end. Any references to places where this behaviour is documented appreciated (because I couldn't find any, or I am using the wrong keywords).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

一桥轻雨一伞开 2024-11-04 22:57:26

这是因为在 a 模式下,写入 FILE* 总是附加到末尾。 fseek 在此模式下仅设置读指针。这在 C 标准 7.19.5.3 fopen 中有记录:

使用附加模式打开文件('a' 作为模式参数中的第一个字符)
导致对文件的所有后续写入都强制到当前的文件结尾,
无论对 fseek 函数的干预调用如何。

That's because in a mode, writing to the FILE* always appends to the end. fseek only sets the read pointer in this mode. This is documented in the C standard, 7.19.5.3 fopen:

Opening a file with append mode ('a' as the first character in the mode argument)
causes all subsequent writes to the file to be forced to the then current end-of-file,
regardless of intervening calls to the fseek function.

眉目亦如画i 2024-11-04 22:57:26

普通 C 没有任何明智的方法来实现你想要的。如果您使用的是 POSIX 系统或任何远程关闭的系统,则可以使用 fd=open(FILENAME, O_CREAT|O_RDRW, 0666),然后使用 fdopen(fd, "rb+")代码>.

编辑:您可以尝试使用普通 C 的另一件事:

f = fopen(FILENAME, "a+b");
if (!f) /* ... */
tmp = freopen(0, "r+b", f);
if (tmp) f = tmp;
else /* ... */

Plain C does not have any sane way to achieve what you want. If you're on a POSIX system or anything remotely close, you can use fd=open(FILENAME, O_CREAT|O_RDRW, 0666) and then fdopen(fd, "rb+").

Edit: Another thing you could try, with plain C:

f = fopen(FILENAME, "a+b");
if (!f) /* ... */
tmp = freopen(0, "r+b", f);
if (tmp) f = tmp;
else /* ... */
呆° 2024-11-04 22:57:26

使用“r+b”模式,如果失败则回退到“w+b”。

“a+b”模式,允许您读取和追加; “r+b”允许随机读写。

fopen 的文档描述了该文件如何具有不同模式的行为。

Use "r+b" mode and fallback to "w+b" if it fails.

The "a+b" mode, allows you to read and append; the "r+b" allows random read and write.

The documentation for fopen describes how the file behaves with the different modes.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文