Linux 如何使用 fopen() 选择打开模式?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10573984/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to choose open mode with fopen()?
提问by Summer_More_More_Tea
I have a problem about file open mode with fopen()
.
我有一个关于文件打开模式的问题fopen()
。
In my case, I want to seek the cursor freely, may be even beyond EOF
sometimes. What's more, I also want to append to it instead of truncating the existing file. I tried to open the file in a+
mode; however, I cannot seek file cursor freely. Each time I seek the cursor beyond EOF
, new arrival data will be append to end of the file, not the position I specified. While, if open in w+
mode, the existing file will be truncated. Is there a perfect solution to this problem?
就我而言,我想自由地寻找光标,EOF
有时甚至可能会超出。更重要的是,我还想附加到它而不是截断现有文件。我试图以a+
模式打开文件;但是,我不能自由地寻找文件光标。每次我寻找超出的光标时EOF
,新到达的数据将附加到文件的末尾,而不是我指定的位置。同时,如果以w+
模式打开,现有文件将被截断。这个问题有完美的解决方案吗?
UPDATE:
更新:
One point not clearly specified is that the file may not always exist; I have to create a new file in that case.
没有明确说明的一点是该文件可能并不总是存在;在这种情况下,我必须创建一个新文件。
In fact, I want to process a configuration file. I don't know whether it is good practice to implement like this. Or should I first place an empty configuration file. Thus there is no need to care about the case file does not exist?
其实我想处理一个配置文件。我不知道这样实施是否是好的做法。或者我应该先放置一个空的配置文件。因而有没有必要在意案件档案不存在?
Below is the code snippet:
下面是代码片段:
FILE *f = fopen(FILE_PATH, "wb+");
struct record r;
if (f) {
if (fread((void *)&r, 1, sizeof(struct record), f) {
/* File exists, do the normal flow */
} else {
if (feof(f)) {
/* File is newly created, do some initialization */
}
}
} else {
/* issue a warning */
}
采纳答案by Jonathan Leffler
You will have to deal with the possibly non-existent file in two stages, first assuming that it is there and then dealing with its absence:
您必须分两个阶段处理可能不存在的文件,首先假设它存在,然后处理它不存在:
if ((f = fopen(filename, "rb+") == 0)
f = fopen(filename, "wb+");
if (f == 0)
...report error...
The "rb+"
mode will fail to open a non-existent file (but otherwise behaves as you want). If the file doesn't exist, then "wb+"
will do what you want instead (though it could still fail, for example if the file exists but you don't have permission to write to it). You have to hope that you've not been subjected to a TOCTOU (Time of Check, Time of Use) attack with the double attempt.
该"rb+"
模式将无法打开一个不存在的文件(但其他方式如您所愿)。如果文件不存在,"wb+"
则将执行您想要的操作(尽管它仍然可能失败,例如,如果文件存在但您没有写入权限)。你必须希望你没有受到两次尝试的 TOCTOU(检查时间,使用时间)攻击。
An alternative approach uses the 3-argument version of the open()
system call with appropriate flags to open a file descriptor, and then uses fdopen()
to create a file stream from the file descriptor:
另一种方法是使用open()
带有适当标志的系统调用的 3 参数版本来打开文件描述符,然后使用fdopen()
该文件描述符创建文件流:
#include <fcntl.h>
int fd;
if ((fd = open(filename, O_RDRW | O_CREAT, 0644)) >= 0)
f = fdopen(fd, "rb+");
You get rather precise control over open()
with the flags.
您可以open()
对标志进行相当精确的控制。
回答by geekosaur
The file modes are clearly documented for fopen
(try man 3 fopen
on Unix/Linux/OS X).
文件模式清楚地记录在案fopen
(man 3 fopen
在 Unix/Linux/OS X 上尝试)。
r+
Open for reading and writing. The stream is positioned at the beginning of the file.
r+
开放阅读和写作。流位于文件的开头。
回答by vincent
Hi, you can use "w+" to read and write by fseek, i wrote a little demo program, write data to file first and use fseek to make each data intervals some byte, and then read it:
你好,fseek可以用w+来读写,我写了一个小demo程序,先把数据写入文件,用fseek把每个数据间隔一个字节,然后读取:
#include <stdio.h>
#include <unistd.h>
#define FILE_PATH "seek_test.txt"
#define STEP_SIZE 64
void set_data(FILE* fp)
{
int i = 0;
fseek(fp, 0, SEEK_SET);
for ( ; i < 20; ++i)
{
fprintf(fp, "%d", i);
fseek(fp, STEP_SIZE, SEEK_CUR);
}
}
void get_data(FILE* fp)
{
int i = 0;
fseek(fp, 0, SEEK_SET);
for ( ; i < 20; ++i)
{
fscanf(fp, "%d", &i);
fprintf(stderr, "Cur Step: %5ld, value = %4d\n", i * STEP_SIZE, i);
fseek(fp, STEP_SIZE, SEEK_CUR);
}
}
int main(int argc, char* argv[])
{
FILE* fp = fopen(FILE_PATH, "w+");
if (fp == NULL)
{
printf("fopen Error\n");
exit(0);
}
set_data(fp);
get_data(fp);
return 0;
}
=============================== result as follows:
============================== 结果如下:
Cur Step: 0, value = 0
当前步骤:0,值 = 0
Cur Step: 64, value = 1
当前步骤:64,值 = 1
Cur Step: 128, value = 2
当前步骤:128,值 = 2
Cur Step: 192, value = 3
当前步骤:192,值 = 3
Cur Step: 256, value = 4
当前步骤:256,值 = 4
Cur Step: 320, value = 5
当前步骤:320,值 = 5
Cur Step: 384, value = 6
当前步骤:384,值 = 6
Cur Step: 448, value = 7
当前步骤:448,值 = 7
Cur Step: 512, value = 8
当前步骤:512,值 = 8
Cur Step: 576, value = 9
当前步骤:576,值 = 9
Cur Step: 640, value = 10
当前步骤:640,值 = 10
Cur Step: 704, value = 11
当前步骤:704,值 = 11
Cur Step: 768, value = 12
当前步骤:768,值 = 12
Cur Step: 832, value = 13
当前步骤:832,值 = 13
Cur Step: 896, value = 14
当前步骤:896,值 = 14
Cur Step: 960, value = 15
当前步骤:960,值 = 15
Cur Step: 1024, value = 16
当前步骤:1024,值 = 16
Cur Step: 1088, value = 17
当前步骤:1088,值 = 17
Cur Step: 1152, value = 18
当前步骤:1152,值 = 18
Cur Step: 1216, value = 19
当前步骤:1216,值 = 19
=============================
==============================