c++ - 为什么 'new line' 偏移 .txt 文件中的所有字符字节位置 +1?

标签 c++ file newline fstream

当我使用 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 确实不会生成非常有意义的数字。我们有这样的东西:

enter image description here

上面是您看到的数据。下方是存储在文件中的数据。当您调用 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/

相关文章:

c++ - 模板推导和 decltype(T) 如何作用于引用?

file - 如果存在同名文件夹,则无法创建文件

git - TFS首次 checkin 的问题(原来是git项目)

java.util.logging 检查文件是否存在于 java 中

php - 在换行符上可靠地拆分用户提交的文本区域值

Redis 在 SET 中回车或换行

c++ - 从文件读取时如何从行中单独读取每个数字

c++ - 类(class)括号后的名字是什么意思?

c++ - 这行三元运算符的语法是什么

c++ - 换行符读了两次