c++ - 为什么“换行”会偏移 .txt 文件中的所有字符字节位置 +1?
问题描述
当我使用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 很失望。
- 我的解决方案:更改 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
,正如问题中所声称的那样。
推荐阅读
- python - Sublime Text 3 REPL 在运行 plt.show() 后停止接受输入
- java - 如何确定我的 Java 应用程序在哪个监视器中运行?
- vuetify.js - 在 Vuetify 中继承 prop 样式
- php - 如何在 PHP 5.6 中向 APNS 发送 http2 请求
- swift - 如果 Swift 还需要参数顺序,为什么它还需要参数名称?
- python - 文件 shell 中的 Python Foreach 行在 linux 上执行命令,然后将输出回显到文件
- azure - Azure Active Directory 身份验证 Javascript
- reactjs - 在 Material-UI 中以编程方式打开 Tooltip
- wpf - WPF:项目容器不属于项目集合
- powershell - Register-ScheduledTask : 未完成帐户名称和安全 ID 之间的映射