以下代码适用于双向流,并从文件中查找记录ID,然后从文件中替换该记录的内容。但是在覆盖内容之前,它会将put指针移到get指针的位置。通过tellp()
和tellg()
,发现它们在移位之前已经在同一位置。但是在删除seekp()
行时,代码不会覆盖数据。
data.txt中的内容:
123 408-555-0394
124 415-555-3422
263 585-555-3490
100 650-555-3434
代码:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
int inID = 263;
const string& inNewNumber = "777-666-3333";
fstream ioData("data.txt");
// Loop until the end of file
while (ioData.good()) {
int id;
string number;
// Read the next ID.
ioData >> id;
// Check to see if the current record is the one being changed.
if (id == inID) {
cout << "get pointer position " << ioData.tellg() << endl; //Displays 39
cout << "put pointer position " << ioData.tellp() << endl; //Displays 39
ioData.seekp(ioData.tellg()); //Commenting this line stops code from working
ioData << " " << inNewNumber;
break;
}
// Read the current number to advance the stream.
ioData >> number;
}
return 0;
}
问题:
当get和put指针一起移动时,需要使用
seekp()
移动put指针的位置(如果已经存在)? 最佳答案
@Revolver_Ocelot在评论中链接的问题提供了相关信息。最重要的部分是您必须刷新或在读写访问之间进行搜索。因此,我通过以下方式修改了您的代码:
if (id == inID) {
cout << "get pointer position " << ioData.tellg() << endl; //Displays 39
cout << "put pointer position " << ioData.tellp() << endl; //Displays 39
ioData.flush();
cout << "get pointer position " << ioData.tellg() << endl;
cout << "put pointer position " << ioData.tellp() << endl;
ioData.seekp(ioData.tellg()); //Commenting this line stops code from working
ioData << " " << inNewNumber;
break;
}
这给出了以下有趣的输出:
(调用
flush()
并不能真正解决问题。我只是将其添加到您的代码中,以向您显示它修改了文件指针。)我对原始代码的假设如下:如果先读取文件后写入文件,而没有在两者之间调用
seekp()
,则在实际将数据写入文件之前,文件指针会被write命令修改。我假设write命令执行某种刷新,并且修改文件指针的方式与我添加到您的代码中的flush()
命令类似。当我在PC上运行上述代码时,
flush()
命令将文件指针移至位置72。如果我们从原始代码中删除seekp()
命令,我认为写命令还将文件指针移至位置72(或者也许实际写入文件之前)。在这种情况下,写入失败,因为位置72在文件末尾之后。因此,需要
ioData.seekp(ioData.tellg());
来确保将文件指针设置为正确的文件位置,因为当您在不调用seekp()
的情况下读写文件之间切换时,它可能会更改。this answer的最后一段给出了类似的解释。