从文件中读取返回我没想到的结果,试图理解为什么



我有这个代码,它包含一个类和一个主函数:

class Employee {
    int m_id;
    string m_name;
    int m_age; public:
    Employee(int id, string name, int age) :m_id(id), m_name(name), m_age(age) {}
    friend ostream& operator<<(ostream& os, const Employee& emp)
    {
        os << emp.m_id << " " << emp.m_name << " " << emp.m_age
           << endl;     
        return os;
    }
};
int main() {
    const int Emp_Num = 3;
    fstream fs("dataBase.txt", ios::out);
    if (!fs) {
        cerr << "Failed opening file. Aborting.n";
        return -1;
    }
    Employee* list[Emp_Num] = 
        { new Employee(1234, "Avi", 34),
          new Employee(11111, "Beni", 24),
          new Employee(5621, "Reut", 26) };
    for (int i = 0; i < Emp_Num; i++) 
    {
        fs << (*list[i]);
        delete list[i];
    }
    fs.close();
    fs.open("dataBase.txt");
    if (!fs) {
        cerr << "Failed opening file. Aborting.n";
        return -1;
    }
    fs.seekg(4);
    string strRead;
    fs >> strRead;
    cout << strRead << endl;
    fs.seekg(6, ios::cur);
    fs >> strRead;
    cout << strRead << endl;
    fs.seekg(-9, ios::end);
    fs >> strRead;
    cout << strRead << endl;
}

以下是我的理解,在第一个文件打开和关闭后,文件dataBase.txt应该是这样的:

1234 Avi 34

11111 Beni 24

5621 Reut 26

我的问题是读取和输出到控制台。打开文件后,我当前位置的指针位于第一个字节,即1234之前的1

我从文件的开头查找4,所以我的指针应该在CCD_ 4和CCD_。

现在我将下一个字符串放入字符串变量CCD_ 6中,现在CCD_ 7包含";Avi";并且指针应该在CCD_ 9的CCD_

现在我从我现在的位置上寻找6,据我统计,这是我通过的6个字节:

  1. Space

  2. 3

  3. 4

  4. Line break (return)

  5. 1

  6. 1

所以我的指针应该在第二行,在两个第一行之后。

我的意思是:

11 | 111 Beni 24

现在我得到了strRead的字符串,根据我对代码strRead的理解,现在应该包含";111〃;,相反,由于某种原因,它包含并稍后输出";1111";。

有人能解释一下为什么它是这样工作的吗?第一行的drop和第二行的第一个字母之间没有字符,所以它应该只算作1个字节。。。

我做了以下测试:

我已经在一个文本为的文件上运行了您代码的第二部分(从文件中读取)

1234 Avi 34 11111 Beni 24 5621 Reut 26

因此,我用空格替换了行的末尾,并且打印到控制台的代码输出预期结果111。然后,我开始怀疑seek会跳过行的末尾。

然后我改了代码(没有修改文件),并以二进制模式处理文件:

//...
fstream fs("dataBase.txt", ios::out | ios::binary);
//...
fs.open("dataBase.txt",  ios::in | ios::binary );
//...

结果再次达到预期:111

这两种情况都有什么变化

好吧,在纯文本(而不是二进制模式)中,行的末尾实际上是2个字符(这可能因其他平台而异,我在Windows上复制它):rn。这就是为什么你读四个一(1111)而不是三个(111)。

Avi:后的空间计数6个位置

  A v i _ 3 4 r n 1 1 1 1 1
                    ^
        1 2 3  4  5 6 7 8

在我执行的第一个测试中,一个空格(只有一个字符)替换了其中的两个字符。

  A v i _ 3 4 _ 1 1 1 1 1
                  ^
        1 2 3 4 5 6 7 8

在二进制模式下,这两个字符都表示为一个单独的读取单元(我没有研究过这是否与平台有关)。

A v i _ 3 4 B 1 1 1 1 1
                ^
      1 2 3 4 5 6 7 8

B代表一些二进制代码。

最新更新