我正在寻找关于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()
函数发现任何错误,请与我们联系。
答案 0 :(得分:22)
班级模板std::basic_filebuf
拥有单个档案位置
§27.9.1.1
- class basic_filebuf关联两个输入 序列和带文件的输出序列。
- 读取和编写由basic_filebuf类对象控制的序列的限制与for相同 使用标准C库文件进行读写。
- 特别是:
醇>
- 如果文件没有打开读取,则无法读取输入序列。
- 如果文件未打开以进行写入,则无法写入输出序列。
- 为输入序列和输出序列维护联合文件位置。
这意味着当您使用std::basic_fstream
时,默认使用std::basic_filebuf
,seekp()
和seekg()
移动单个文件位置;除非你使用一个单独的变量来存储其中一个仓位,这样你就可以追回它,你无法独立跟踪看跌和获取仓位。
第2点的含义是在fstream
上的读取和写入之间,您必须刷新缓冲区或在从输出更改为输入时搜索文件位置,并且您必须位于文件的末尾或者在从输入切换到输出时寻找文件位置。
有关这些限制的详细信息,请参阅C99标准的第7.19.5.3/7节(“fopen
函数”)或C11的7.21.5.3/7。