get() 的异常行为(从 C++ 中的文件读取)
Unusual behaviour of get() (reading from a file in c++)
// Print the last n lines of a file i.e implement your own tail command
#include <iostream>
#include <fstream>
#include <string>
int main()
{
std::ifstream rd("D:\BigFile.txt");
int cnt = 0;char c;
std::string data;
rd.seekg(0,rd.end);
int pos=rd.tellg();
while(1)
{
rd.seekg(--pos,std::ios_base::beg);
rd.get(c);
if(c=='\n')
{
cnt++;
// std::cout<<pos<<"\t"<<rd.tellg()<<"\n";
}
if(cnt==10)
break;
}
rd.seekg(pos+1);
while(std::getline(rd,data))
{
std::cout<<data<<"\n";
}
}
所以,我编写了这个程序来打印文本文件的最后 10 行。但是它只打印最后一个 5 ,出于某种原因每次遇到实际的 '\n' 下一个 get() 也会给出一个 \n 导致不正确的输出。这是我的输入文件:
Hello
Trello
Capello
Morsello
Odello
Othello
HelloTrello
sdasd
qerrttt
mkoilll
qwertyfe
我在 Windows 上使用记事本,这是我的输出:
HelloTrello
sdasd
qerrttt
mkoilll
qwertyfe
我不明白为什么会这样,请帮忙。
如果文件以文本模式打开,请不要对文件位置进行算术运算。它不会给你正确的结果。
如果以文本模式打开文件,1 个字符并不总是意味着 1 个字节。以及如何实现文件位置(如果它指向特定字符或字节)未指定。
在您的情况下,问题是 Windows 上的换行符有两个字节长。文本流将其转换为单字节符号 '\n'
,因此您无需担心平台和实际使用的字节序列之间的差异。
所以您的第一次读取读取的是双字节结束符号的最后一个字节,它恰好与 ASCII 中的 '\n'
具有相同的值。下一次读取落在两字节结束符号的开头,流将其正确转换为 '\n'
.
// Print the last n lines of a file i.e implement your own tail command
#include <iostream>
#include <fstream>
#include <string>
int main()
{
std::ifstream rd("D:\BigFile.txt");
int cnt = 0;char c;
std::string data;
rd.seekg(0,rd.end);
int pos=rd.tellg();
while(1)
{
rd.seekg(--pos,std::ios_base::beg);
rd.get(c);
if(c=='\n')
{
cnt++;
// std::cout<<pos<<"\t"<<rd.tellg()<<"\n";
}
if(cnt==10)
break;
}
rd.seekg(pos+1);
while(std::getline(rd,data))
{
std::cout<<data<<"\n";
}
}
所以,我编写了这个程序来打印文本文件的最后 10 行。但是它只打印最后一个 5 ,出于某种原因每次遇到实际的 '\n' 下一个 get() 也会给出一个 \n 导致不正确的输出。这是我的输入文件:
Hello
Trello
Capello
Morsello
Odello
Othello
HelloTrello
sdasd
qerrttt
mkoilll
qwertyfe
我在 Windows 上使用记事本,这是我的输出:
HelloTrello
sdasd
qerrttt
mkoilll
qwertyfe
我不明白为什么会这样,请帮忙。
如果文件以文本模式打开,请不要对文件位置进行算术运算。它不会给你正确的结果。
如果以文本模式打开文件,1 个字符并不总是意味着 1 个字节。以及如何实现文件位置(如果它指向特定字符或字节)未指定。
在您的情况下,问题是 Windows 上的换行符有两个字节长。文本流将其转换为单字节符号 '\n'
,因此您无需担心平台和实际使用的字节序列之间的差异。
所以您的第一次读取读取的是双字节结束符号的最后一个字节,它恰好与 ASCII 中的 '\n'
具有相同的值。下一次读取落在两字节结束符号的开头,流将其正确转换为 '\n'
.