24

我正在寻找有关您何时写入文件的方式seekg()和工作方式的一些说明。seekp()比如说我有一个像这样的文件:

offset 0: 2
offset 4: 4
offset 8: 6
offset 12: 8
offset 16: 10

现在我想打开文件并尝试读取和写入值。

fstream file;
file.open("file.txt", fstream::in |fstream::out | fstream::binary);
file.seekp(0, ios::end) // seek to the end of the file
int eofOffset = file.tellp(); // store the offset of the end-of-file, in this case 20

int key = 0;

file.seekg(12, ios::beg); // set the seek cursor to offset 12 from the beginning of the file
file.read((char *) &key, (int)sizeof(int)); // read in the next 4 bytes and assign it to key, in this case 8
file.seekg(8, ios::beg); // set the seek cursor to offset 8 from the beginning of the file
file.read((char *) &key, (int)sizeof(int)); // read in the next 4 bytes and assign it to key, in this case 6

现在我想写到文件的末尾。由于该seekg()函数只移动搜索光标,我的seekp()光标应该仍然在文件的末尾,对吧?所以:

int newKey = 12;
file.write((char *) &newKey, sizeof(int));

应该使我的文件现在看起来像:

offset 0: 2
offset 4: 4
offset 8: 6
offset 12: 8
offset 16: 10
offset 20: 12

现在,如果我选择寻找偏移量并将其值作为偏移量写入刚刚插入的值,我的文件会发生什么情况。例如,我想offset 8保留eofOffset = 20,因为我们刚刚在那个偏移量处插入了 12。

如果我做:

file.seekp(8, ios::beg);
file.write((char *) &eofOffset, sizeof(int));

它是否正确地将我的文件重写为如下所示:

offset 0: 2
offset 4: 4
offset 8: 20
offset 12: 8
offset 16: 10
offset 20: 12

seekg()如果我在使用和seekp()函数时出现任何错误,请告诉我。

4

1 回答 1

24

类模板std::basic_filebuf保存单个文件位置

§ 27.9.1.1

  1. basic_filebuf 类将输入序列和输出序列都与文件相关联。
  2. 读取和写入由类 basic_filebuf 的对象控制的序列的限制与使用标准 C 库 FILE 读取和写入的限制相同。
  3. 尤其:
    • 如果文件未打开以进行读取,则无法读取输入序列。
    • 如果文件未打开以进行写入,则无法写入输出序列。
    • 为输入序列和输出序列维护一个联合文件位置。

这意味着当您使用 astd::basic_fstream时,默认情况下使用 a std::basic_filebuf,单个文件的位置会同时被seekp()和移动seekg();除非您使用单独的变量来存储其中一个位置,以便您随后可以回溯到它,否则您无法单独跟踪 put 和 get 位置。

第 2 点的含义是,在读取和写入之间,fstream您必须在从输出更改为输入时刷新缓冲区或查找文件位置,并且您必须在文件末尾或从更改时查找文件位置输入输出。

有关这些限制的详细信息,请参阅 C99 标准的第 7.19.5.3/7 节(“fopen函数”)或 C11 的第 7.21.5.3/7 节。

于 2013-03-28T03:02:06.340 回答