使用 lseek 和 write 导致输入行被追加

Using lseek and write lead to input lines getting appended

我想逐行写入文件,但我做不到。它被附加在同一行中。请帮忙。

示例代码如下:

int main()
 {
     long filesize;
     char sentence[1000];
     int count = 5;
     int m_iSourceFileData;
     int i = 0;
     long offset =0;

    if ((m_iSourceFileData = open("test.txt", O_RDWR | O_APPEND | O_CREAT,S_IWRITE | S_IREAD)) != -1)
     {
         while(i != count)
         {
             if ((lseek(m_iSourceFileData, offset, SEEK_SET)) != -1)
             {
                 printf("Enter a sentence: %d\n", i);
                 gets(sentence);
                 filesize = strlen(sentence);
                 write(m_iSourceFileData, sentence, filesize);
                 offset += filesize;
                 printf("Offset is %ld, filesize:%ld\n",offset,filesize);
                 i++;
             }

         }

         if(m_iSourceFileData != -1)
         {
             close(m_iSourceFileData);
             m_iSourceFileData = -1;
         }
     }
}

输入

$ a.out
Enter a sentence: 0
write
Offset is 5, filesize:5
Enter a sentence: 1
into
Offset is 9, filesize:4
Enter a sentence: 2
file
Offset is 13, filesize:4
Enter a sentence: 3
line after
Offset is 23, filesize:10
Enter a sentence: 4
line
Offset is 27, filesize:4

输出

writeintofileline afterline

不要使用gets,这是一个不检查边界的危险函数, 它也从 C11 标准中删除。请改用 fgets

gets returns 包含一行的字符串,但是它不保存换行符 字符 '\n'.

write(m_iSourceFileData, sentence, filesize);

如果 sentence 没有换行符,你为什么期望在 输出文件? write 忘记了你的意图,它不会附加换行符 因为你想要它。

您有两个选择:

第一种(不推荐):在字符串后面追加一个换行符:

strcat(sentence, "\n");
filesize = strlen(sentence);
write(m_iSourceFileData, sentence, filesize);

第二(推荐):永远不要使用gets,而是使用fgetsfgets 确实保存换行符(如果有 缓冲区中的 space 就足够了)。参见 fgets

printf("Enter a sentence: %d\n", i);
fgets(sentence, sizeof sentence, stdin);
filesize = strlen(sentence);
write(m_iSourceFileData, sentence, filesize);

您应该始终检查与 交互的函数的 return 值 外面的世界,比如 fgets。你应该经常检查 fgets 没有 return NULL.

这个

open("test.txt", O_RDWR | O_APPEND | O_CREAT,S_IWRITE | S_IREAD)

以附加模式打开文件,因为 flags 包含 O_APPEND

根据 the POSIX open() documentation:

...

Any combination of the following may be used:

O_APPEND

If set, the file offset shall be set to the end of the file prior to each write.

...

如果你想写入以附加模式打开的文件中的特定偏移量,你 can use pwrite():

The pwrite() function shall be equivalent to write(), except that it writes into a given position and does not change the file offset (regardless of whether O_APPEND is set). The first three arguments to pwrite() are the same as write() with the addition of a fourth argument offset for the desired position inside the file. An attempt to perform a pwrite() on a file that is incapable of seeking shall result in an error.

但是,如果您是 运行 Linux,pwrite() is broken:

BUGS

POSIX requires that opening a file with the O_APPEND flag should have no effect on the location at which pwrite() writes data. However, on Linux, if a file is opened with O_APPEND, pwrite() appends data to the end of the file, regardless of the value of offset.