从文件 returns 读取一个我没想到的结果,试图理解为什么
Reading from file returns a result I didn't expect, trying to understand why
我有这段代码,其中包含一个 class 和一个主要函数:
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,
所以我的指针应该在 1234
和 Avi
之间的 space 之前(之前)。
现在我将下一个字符串放入我的字符串变量 strRead
,
现在 strRead
包含“Avi”,指针应该在 Avi
的 i
和它后面的 space 之间。
现在我从我现在的位置求6,
据我统计,这些是我通过的 6 个字节:
Space
3
4
Line break (return)
1
1
所以我的指针应该在第二行,在前两行之后。
我的意思是这样的:
11|111 Beni 24
现在我得到一个 strRead
的字符串,根据我对代码 strRead
的理解,现在应该包含“111”,而不是,出于某种原因,它包含并稍后输出“1111”。
有人可以解释一下为什么会这样吗?
第一行drop和第二行第一个字母之间没有字符,所以应该只算1个字节...
我做了以下测试:
我有 运行 你的代码的第二部分(从文件中读取)在一个文件中,文本为:
1234 Avi 34 11111 Beni 24 5621 Reut 26
所以,我用 spaces 替换了 行尾 ,代码打印到控制台输出了预期的结果 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
之后的 space 算起 6 个位置:
A v i _ 3 4 \r \n 1 1 1 1 1
^
1 2 3 4 5 6 7 8
在我执行的第一个测试中,space(只有一个字符)替换了其中两个。
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 在这里代表一些二进制代码。
我有这段代码,其中包含一个 class 和一个主要函数:
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,
所以我的指针应该在 1234
和 Avi
之间的 space 之前(之前)。
现在我将下一个字符串放入我的字符串变量 strRead
,
现在 strRead
包含“Avi”,指针应该在 Avi
的 i
和它后面的 space 之间。
现在我从我现在的位置求6, 据我统计,这些是我通过的 6 个字节:
Space
3
4
Line break (return)
1
1
所以我的指针应该在第二行,在前两行之后。
我的意思是这样的:
11|111 Beni 24
现在我得到一个 strRead
的字符串,根据我对代码 strRead
的理解,现在应该包含“111”,而不是,出于某种原因,它包含并稍后输出“1111”。
有人可以解释一下为什么会这样吗? 第一行drop和第二行第一个字母之间没有字符,所以应该只算1个字节...
我做了以下测试:
我有 运行 你的代码的第二部分(从文件中读取)在一个文件中,文本为:
1234 Avi 34 11111 Beni 24 5621 Reut 26
所以,我用 spaces 替换了 行尾 ,代码打印到控制台输出了预期的结果 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
之后的 space 算起 6 个位置:
A v i _ 3 4 \r \n 1 1 1 1 1
^
1 2 3 4 5 6 7 8
在我执行的第一个测试中,space(只有一个字符)替换了其中两个。
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 在这里代表一些二进制代码。