gpt4 book ai didi

c++ - 在文本模式下使用 seekg()

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:37:37 26 4
gpt4 key购买 nike

在尝试以文本模式 (Windows) 读取一个简单的 ANSI 编码文本文件时,我遇到了 seekg()tellg() 的一些奇怪行为;任何时候我尝试使用 tellg(),保存它的值(作为 pos_type),然后稍后再寻找它,我总是会在流中比我离开的地方更靠前。

最后我进行了完整性检查;即使我只是这样做...

int main()
{
std::ifstream dataFile("myfile.txt",
std::ifstream::in);
if (dataFile.is_open() && !dataFile.fail())
{
while (dataFile.good())
{
std::string line;
dataFile.seekg(dataFile.tellg());
std::getline(dataFile, line);
}
}
}

...然后最终,进一步进入文件,行被截断了一半。为什么会发生这种情况?

最佳答案

此问题是由于 libstdc++ 使用当前剩余缓冲区与 lseek64 之间的差异来确定当前偏移量引起的。

缓冲区使用 read 的返回值设置,对于 windows 上的文本模式文件,返回行尾转换后放入缓冲区的字节数(即 2 字节 \r\n endline 被转换为 \n,windows 似乎也在文件末尾附加了一个虚假的换行符)。

lseek64 但是(使用 mingw 会导致调用 _lseeki64)返回当前的绝对文件位置,一旦减去这两个值,您就会得到一个偏移量文本文件中每个剩余的换行符都减 1(额外换行符 +1)。

以下代码应该会显示问题,您甚至可以使用具有单个字符且没有换行符的文件,因为 windows 会插入额外的换行符。

#include <iostream>
#include <fstream>

int main()
{
std::ifstream f("myfile.txt");

for (char c; f.get(c);)
std::cout << f.tellg() << ' ';
}

对于具有单个 a 字符的文件,我得到以下输出

2 3

对于 tellg 的第一次调用明显偏离 1。第二次调用后,文件位置正确,因为考虑到额外的换行符后已到达结尾。

除了以二进制模式打开文件外,您还可以通过禁用缓冲来规避此问题

#include <iostream>
#include <fstream>

int main()
{
std::ifstream f;
f.rdbuf()->pubsetbuf(nullptr, 0);
f.open("myfile.txt");

for (char c; f.get(c);)
std::cout << f.tellg() << ' ';
}

但这远非理想。

希望 mingw/mingw-w64 或 gcc 可以解决这个问题,但首先我们需要确定谁负责修复它。我想基本问题在于 MS 的 lseek 实现,它应该根据文件的打开方式返回适当的值。

关于c++ - 在文本模式下使用 seekg(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27055771/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com