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

时间:2015-06-22 16:05:37

标签: c++ string file-io fstream

我有这个包含类和主函数的代码:

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

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

我从文件的开头寻求4, 所以我的指针应位于1234Avi之间的空格之前。

现在我将下一个字符串放入我的字符串变量strRead, 现在strRead包含&#34; Avi&#34;并且指针应该在i Avi和它之后的空格之间。

现在我从现在的位置寻求6, 按我的计算,这是我通过的6个字节:

  1. Space

  2. 3

  3. 4

  4. Line break (return)

  5. 1

  6. 1

  7. 所以我的指针应该位于第二行之后的第二行。

    我是这样的意思:

      

    11 | 111 Beni 24

    现在我得到一个字符串strRead,我对代码strRead的理解现在应该包含&#34; 111&#34;而是出于某种原因,它包含并稍后输出& #34; 1111&#34;

    有人可以解释一下为什么它会这样运作? 第一行放置和第二行的第一个字母之间没有字符,因此它应该只计为1个字节......

1 个答案:

答案 0 :(得分: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上重现这一点):\r\n 。这就是你读四个(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空格(只有一个字符)替换了其中两个。

  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代表一些二进制代码。