很多时候,我们用getline函数读取文本文件的每一行,留待以后进行处理(如:用istringstream对象解析行中的内容),代码片段如下:
ifstream in ("Test.txt");
if (!in)
return ;
string sLine;
while (getline (in, sLine))
{
// do something......
}
不过最近在处理一个文本的时候,发现getline读取到文件中间的某一行,就返回false了。不能读取完整个文件。我到文本文件的那一行用UE去看,发现很多乱码,显示如下:
&_N??/f?:N?l??JT???I{?_ @b???*N?NMbOUS@w0
debug进入到getline函数内部,看到代码如下:
const typename _Traits::int_type _Metadelim = _Traits::to_int_type(_Delim); typename _Traits::int_type _Meta = _Istr.rdbuf()->sgetc();
for (; ; _Meta = _Istr.rdbuf()->snextc()) if (_Traits::eq_int_type(_Traits::eof(), _Meta)) { // end of file, quit _State |= ios_base::eofbit; break; } else if (_Traits::eq_int_type(_Meta, _Metadelim)) { //
got a delimiter, discard it and quit _Changed = true; _Istr.rdbuf()->sbumpc(); break; } else if (_Str.max_size() <= _Str.size()) { //
string too large, quit _State |= ios_base::failbit; break; } else { // got a character, add it to string _Str += _Traits::to_char_type(_Meta); _Changed = true; } _CATCH_IO_(_Istr) } |
代码逻辑很简单,就是一个for循环,不断读取字符,并做判断,分以下四种情况:
1. 遇到文件结尾(end of file),设置状态为ios_base::eofbit后返回
2. 遇到分隔符(delimiter),丢弃掉分隔符,并break出循环
3. 当字符串太大,无法存储,设置状态ios_base::failbit后返回
4. 否则,将字符attach到字符串尾部,继续循环。
debug发现,getline是在情况1的时候退出的,就是遇到了文件尾。
接下来的问题,文件尾是什么?上网上看了下,文本文件没有一个特定的字符来表示文件末尾,不像c字符串用'\0'来表示文件尾。文件尾字符的存在没有必要,因为文件对象已经记录了文件的大小。在读取的时候,随时判断是否达到了文件的大小;如果达到了,就返回EOF。EOF在VS中用宏在stdio.h中定义为-1,代码如下:
#define EOF (-1)
上面代码中_Traits::eof()就是返回EOF的值。
分析原因,是在文本文件流中有一个字符的值是-1(实际值是255,对应blank 'FF',在linux的terminal中,ctrl+D能够在流中插入文件尾,表示用户结束屏幕输入),这个字符被正常独取出来,而读取的总字符数也没有达到文件大小,但是getline在这个字符和EOF比较中,发现两者相等,就认为读取到了文件尾,就结束读取,设置流的相关状态,blablalblaa...,以后的都知道了。
那么这个问题如何解?网上给了一个方法:用二进制形式读取。因为对于文本文件,-1意味着文件尾;而对于二进制文件,-1并不是文件尾。而且,看getline源代码,可以在二进制模式下工作。
修正上面的读取代码为:
ifstream in ("Test.txt", ios_base::binary);
if (!in)
return ;
string sLine;
while (getline (in, sLine))
{
// do something......
}
读取成功,问题解决。
接下来,我又将读取的内容写到文本文件中,代码如下:
ifstream in ("Test.txt",ios_base::binary);
ofstream out ("Test2.txt")
if (!in || !out)
return ;
string sLine;
while (getline (in, sLine))
{
out << sLine <<"\n";
}
用文本文件方式读取,依然出问题;用二进制ios_base::binary读取,依然没问题,呵呵。看来输出流是把输入流(无论是文本形式还是二进制形式)中的内容原原本本地写到文件中了,这中间没有任何过滤行为。
OK,问题解决,写完。
分享到:
相关推荐
之前在使用C++中的getline读取文本文件时由于没有仔细看getline的定义,导致出了错:在读取文本文件时未读取到文件中的第一行。 错误的源代码如下: vectorreadfile(string s1,vectorv1) { ifstream infile...
c++、getline、每次读取一行txt; //读取方式: 逐词读取, 词之间用空格区分; //读取方式: 逐行读取, 将行读入字符数组, 行之间用回车换行区分; //读取方式: 逐行读取, 将行读入字符串, 行之间用回车换行区分
ifstream和getline读取文件
getline 模板函数读取遇到分隔符后的多余的字符
首先打开vim配置文件 sudo vim etc vim vimrc 然后插入 51 :set hlsearch #高亮搜索 52 set number #显式行号 53 :set showmatch 54 :set foldmethod expr #定义折叠方式为自定义表达式 55 :set foldexpr ...
STL是三维模型常用的文件格式。...再用标准库string类型中的getline逐行读取绑定的STL文件;最后, 应用 OpenGL 中绘制三角面片编程技术实现对 STL 文件格式的直观显示。通过试验验证了读取和显 示效果。
比如: import linecacheprint linecache.getline... 您可能感兴趣的文章:python逐行读取文件内容的三种方法Python按行读取文件的简单实现方法Python3读取文件常用方法实例分析Python实现读取文件最后n行的方法Pyth
较简单的程序代码,示例了getline函数使用技巧
关于getline函数的详细方法说明,希望对刚学习c++的同胞们有点帮助
微软已经确定vc++6.0中getline函数使用时有bug,并提出了解决方法!
如果您以“任何其他方式”读取文件的行,它们仍将是相同的行。 它不会解决文件“格式”的问题。 这个问题毫无意义。例如,您可以使用std :: istream :: getline:...
getline()用法 getline是C++标准库函数;它有两种形式,一种是头文件中输入流成员函数;一种在头文件中普通函数; 它遇到以下情况发生会导致生成的本字符串结束: (1)到文件结束,(2)遇到函数的定界符,(3)输入达到...
Cin.getline终极用法1
使用while循环和std::getline函数从文件中逐行读取内容。std::getline函数会从inputFile中读取一行内容,并将其存储在line变量中。如果读取成功,则继续循环;如果到达文件末尾或发生错误,则退出循环。 在循环体内...
# linecache读取并缓存文件中所有的文本, # 若文件很大,而只读一行,则效率低下。 # 可显示使用循环, 注意enumerate从0开始计数,而line_number从1开始 def getline(the_file_path, line_numbe
get和getline所属iostream类,作用是读取一整行,通过换行符确定读取结束,他们都可以读取空格。 2、get与getline区别 getline会在读取结束后舍弃换行符,而get回将换行符保留到输入序列中。 char arr[100]; cout&...
这个getline函数输入要击两次回车的解决办法不错..有点实用
目录 前言 显示和操作文件的实用程序 网络的实用程序 显示和修改状态的实用程序 ...用getline读取行 4.2.4.用样式对awk的行进行过滤 4.2.5.设置字段定界符 4.2.6.从awk中读取命令输出 4.2.7.在awk中使用循环 后续
对一组数据进行快速排序,使用vector进行存储数据,动态数组,需要创建一个txt文本,逐行读取getline的经典应用