fopen 的第二个参数

发布于 2024-10-13 05:24:26 字数 416 浏览 7 评论 0原文

好的,所以我正在编写一个游戏,在这个游戏中,有一个交互式设置菜单。我想要做的是写入文件(如果不存在),从文件中读取(如果存在),应用文件中指定的设置,并使用用户的新设置覆盖它(如果用户选择更改设置) 。所以它会像这样(伪代码):

if (file does not exist)
    write_defaults
open settings
read from file
apply settings specified in file
while (user is changing settings)
    if (user is done) break
write new settings to file
apply new settings

现在我将用什么来表示 fopen 的第二个参数?我尝试过“r+”和“w+”,但都遇到了问题。

OK, so I'm writing a game, and in this game, there's an interactive settings menu. What I want to do is write to the file if it doesn't exist, read from the file if it does, apply settings specified in the file, and overwrite it with new settings from the user, if the user chooses to change the settings. So it would go something like this (psuedo-code):

if (file does not exist)
    write_defaults
open settings
read from file
apply settings specified in file
while (user is changing settings)
    if (user is done) break
write new settings to file
apply new settings

Now what would I use for fopen's second argument? I've tried both "r+" and "w+" but I've had problems with both.

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

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

发布评论

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

评论(3

情魔剑神 2024-10-20 05:24:26

对于写入操作,我将打开为 "w" ,对于读取操作,将重新打开为 "r" ,除非您正在进行某种随机访问同时读取/写。

正如 @stefan 在下面的评论中提到的,如果您要操作原始二进制数据而不是文本,则需要 "rb""wb"

I would open as "w" for the write operations, and reopen as "r" for the read operations, unless you're doing some sort of random-access simultaneous read/write.

As @stefan has mentioned in a comment below, you would want "rb" or "wb" if you are manipulating raw binary data rather than text.

躲猫猫 2024-10-20 05:24:26

只需使用“r+”打开文件即可。检查返回的指针,如果指针不为NULL,则从文件中读取设置。然后写入文件。

Just open the file with "r+". Check the returned pointer, if the pointer is not NULL, read settings from file. Then write to file.

我偏爱纯白色 2024-10-20 05:24:26

第一次尝试使用 "r+" 是正确的;如果由于文件不存在而失败,则使用 "w+" 重试。这将为您提供一个打开以进行更新的文件,但如果文件已存在,则不会破坏该文件。

然而,从某种意义上说,这是次优的,因为存在 TOCTOU(检查时间,使用时间)漏洞 - 如果文件是在使用 "r+" 打开失败和使用 成功打开之间创建的"w+",文件中的信息将会丢失。

如果您有权访问 POSIX 函数,则可以使用 open() 而不是 fopen() 在一次原子尝试中正确完成这项工作,然后使用 fdopen( ) 将文件描述符转换为文件流。

FILE *carefully_open(const char *file)
{
    int fd = open(file, O_RDWR | O_CREAT, 0644);
    FILE *fp = 0;

    if (fd >= 0)
        fp = fdopen(fd, "r+");
    if (fd >= 0 && fp == 0)
        close(fd);
    return fp;
}

这样做的一个缺点是它将通过损坏的符号链接创建一个文件。您可以使用 O_EXCL 标志来避免这种情况,但如果文件确实存在,则打开将失败。毕竟,您最终会对 open() 进行两次调用,一次仅使用 O_RDRW,第二次使用 O_RDRW | O_CREAT | O_EXCL 可以安全地防止遵循损坏的符号。

(什么是损坏的符号链接?如果当前目录中没有文件 pqr,则 ln -s ./pqr xyz 表示 xyz 是损坏的符号链接将通过使用显示的 open() 调用创建文件“pqr”来“修复”。)

您遇到了什么问题?

Using "r+" is correct for the first attempt; if it fails because the file does not exist, then try again with "w+". This gives you a file open for update, but doesn't clobber a file if it already exists.

However, this is sub-optimal in the sense that there's a TOCTOU (time of check, time of use) vulnerability - if the file is created between the failed open with "r+" and the successful open with "w+", the information in the file will be lost.

If you have access to POSIX functions, you can use open() instead of fopen() to do the job correctly in one atomic attempt, followed by fdopen() to convert the file descriptor into a file stream.

FILE *carefully_open(const char *file)
{
    int fd = open(file, O_RDWR | O_CREAT, 0644);
    FILE *fp = 0;

    if (fd >= 0)
        fp = fdopen(fd, "r+");
    if (fd >= 0 && fp == 0)
        close(fd);
    return fp;
}

The one downside to this is that it will create a file through a broken symlink. You can avoid that with the O_EXCL flag, but then the open will fail if the file does exist. You end up making two calls to open() after all, one with just O_RDRW and the second with O_RDRW | O_CREAT | O_EXCL to be safe against following broken symlnks.

(What is a broken symlink? If there is no file pqr in the current directory, ln -s ./pqr xyz means that xyz is a broken symlink that will be 'fixed' by creating file 'pqr' with the open() call shown.)

What problems did you have?

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