当我使用 fstream::tellg
时, 在用 fstream::get (char)
读入第一个字符后结果是:1
然后我在第一个字符后插入一个“新行”
我fstream::seekg
到开头:0
当我使用 fstream::tellg
时, 这次读入第一个字符后
结果是:2
如果我插入:"abc"
, 到 .txt 文件中:
- 阅读“a”后
tellg
将给出:1 - 在“b”2 之后
- 和“c”3 之后。
但是如果我插入:"abc\n"
或 "abc" << endl;
:
- 阅读“a”后
tellg
会给2 - 在“b”3之后
- 在“c”4之后
- 新行后的最后 5 个。
这是什么原因?
我知道“换行符”也是字符。我不明白的是 tellg
的抵消读取字符后的结果。每次使用“换行符”时,此偏移量都会增加一个。
更新
- 结论: 我的 IDE 设置有问题! 我一直在使用 Code::Blocks。我尝试在 Microsoft Visual Studio IDE 中构建程序,它运行时没有发现任何问题。这并不意味着 Code::Blocks 已损坏。这可能是我的 Code::Blocks 设置中的一个问题。我不记得改变了什么。即使是这样;以我的愚见,我认为你可以偶然改变这种事情是不对的。我对 Code::Blocks 很失望。
- mySolution:更改 IDE
最佳答案
我猜您是在 Microsoft 操作系统上编写代码。
在文本文件中,Microsoft 操作系统(和相关软件)希望行尾用 \r\n
序列标记,因此当您将换行符写入(文本) 文件,它将从 \n
转换为 \r\n
。因此,即使您只将一个字符插入到流中,也会导致将两个字符写入外部文件。
如果您关心确保外部文件的内容与您插入到流中的内容完全匹配,这可能表明您想要 C++ 标准库认为是二进制文件的内容,您可以通过指定std::ios::binary
当您打开文件时。
现在,当您处理文本文件时,tellg
确实不会生成非常有意义的数字。我们有这样的东西:
上面是您看到的数据。下方是存储在文件中的数据。当您调用 tellg 时,它会告诉您下方的位置,即相对于文件开头的位置。但是,根据文件中前面有多少对\r\n ,这可能会导致上行中的字符数不同,这就是您从文件中读取数据时会看到的内容。
这意味着 tellg 的结果只能以几种相当特定的方式使用——大多数情况下,当你从 tellg 得到一个数字时,你可以将该数字返回给 seekg,然后从同一个地方开始读取.
就您的代码而言,我想我不明白您的问题在说什么。我稍微重写了代码以一起显示结果:
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <string>
using namespace std;
std::string show(char x) {
if (x > 32)
return std::string(1, x);
else switch (x) {
case '\r': return "<\\r>";
case '\n': return "<\\n>";
case '\t': return "<\\t>";
default: return "<BAD>";
}
}
void display_txt_file(fstream& file)
{
file.seekg(0, ios_base::beg);
char x;
cout << "tellg: " << file.tellg() << "| ";
while (file.get(x))
{
cout << "'" << show(x) << "' tellg: " << file.tellg() << "| ";
}
file.clear();
file.seekg(0, ios_base::end);
std::cout << "\n";
// cout << "\n> " << file.tellg() << "\n" << endl;
}
int main(int argc, char* argv[])
{
ofstream new_file;
new_file.open("test.txt");
new_file.close();
fstream file("test.txt", ios::in | ios::out);
if (!file.is_open())
{
cout << "error file not opened" << endl;
return 0;
}
file << "ABCD";
display_txt_file(file);
file.seekp(0);
file << "ABCD\nE";
display_txt_file(file);
return 0;
}
当我在 Windows 上运行它时,我得到以下输出:
tellg: 0| 'A' tellg: 1| 'B' tellg: 2| 'C' tellg: 3| 'D' tellg: 4|
tellg: 0| 'A' tellg: 1| 'B' tellg: 2| 'C' tellg: 3| 'D' tellg: 4| '<\n>' tellg: 6| 'E' tellg: 7|
因此,换行符之前的所有内容都符合我们的预期。然后换行符扩展为两个字符,后跟 E
。但是,在我们读取“A”之后,tellg
返回了 1
,而不是问题中声称的 2
。
关于c++ - 为什么 'new line' 偏移 .txt 文件中的所有字符字节位置 +1?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52748885/