`
cloudtech
  • 浏览: 4611233 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
文章分类
社区版块
存档分类
最新评论

【Q&A】getline读取文本文件的问题

 
阅读更多

很多时候,我们用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读取文本文件

    之前在使用C++中的getline读取文本文件时由于没有仔细看getline的定义,导致出了错:在读取文本文件时未读取到文件中的第一行。 错误的源代码如下: vectorreadfile&#40;string s1,vectorv1&#41; { ifstream infile...

    使用ifstream和getline读取文件内容[c++]

    c++、getline、每次读取一行txt; //读取方式: 逐词读取, 词之间用空格区分; //读取方式: 逐行读取, 将行读入字符数组, 行之间用回车换行区分; //读取方式: 逐行读取, 将行读入字符串, 行之间用回车换行区分

    ifstream和getline读取文件

    ifstream和getline读取文件

    getline 模板函数读取遇到分隔符后的多余的字符.pdf

    getline 模板函数读取遇到分隔符后的多余的字符

    配置vim方便读取android反编译的smali文件

    首先打开vim配置文件 sudo vim etc vim vimrc 然后插入 51 :set hlsearch #高亮搜索 52 set number #显式行号 53 :set showmatch 54 :set foldmethod expr #定义折叠方式为自定义表达式 55 :set foldexpr ...

    opengl读取stl文件

    STL是三维模型常用的文件格式。...再用标准库string类型中的getline逐行读取绑定的STL文件;最后, 应用 OpenGL 中绘制三角面片编程技术实现对 STL 文件格式的直观显示。通过试验验证了读取和显 示效果。

    Python linecache.getline()读取文件中特定一行的脚本

    比如: import linecacheprint linecache.getline... 您可能感兴趣的文章:python逐行读取文件内容的三种方法Python按行读取文件的简单实现方法Python3读取文件常用方法实例分析Python实现读取文件最后n行的方法Pyth

    getline函数示例用法

    较简单的程序代码,示例了getline函数使用技巧

    c++ getline

    关于getline函数的详细方法说明,希望对刚学习c++的同胞们有点帮助

    VC++6.0编译器getline函数的bug处理

    微软已经确定vc++6.0中getline函数使用时有bug,并提出了解决方法!

    逐行读取文本文件,并将每一行保存在缓冲区中,而不管数据类型如何。

    如果您以“任何其他方式”读取文件的行,它们仍将是相同的行。 它不会解决文件“格式”的问题。 这个问题毫无意义。例如,您可以使用std :: istream :: getline:...

    C++中getline()的用法详解

    getline()用法 getline是C++标准库函数;它有两种形式,一种是头文件中输入流成员函数;一种在头文件中普通函数; 它遇到以下情况发生会导致生成的本字符串结束: (1)到文件结束,(2)遇到函数的定界符,(3)输入达到...

    Cin.getline终极用法1

    Cin.getline终极用法1

    C++实现文件读写操作功能(源码+说明文档).zip

    使用while循环和std::getline函数从文件中逐行读取内容。std::getline函数会从inputFile中读取一行内容,并将其存储在line变量中。如果读取成功,则继续循环;如果到达文件末尾或发生错误,则退出循环。 在循环体内...

    Python3实现从文件中读取指定行的方法

    # linecache读取并缓存文件中所有的文本, # 若文件很大,而只读一行,则效率低下。 # 可显示使用循环, 注意enumerate从0开始计数,而line_number从1开始 def getline(the_file_path, line_numbe

    浅谈C++中字符串输入get与getline的区别

    get和getline所属iostream类,作用是读取一整行,通过换行符确定读取结束,他们都可以读取空格。 2、get与getline区别 getline会在读取结束后舍弃换行符,而get回将换行符保留到输入序列中。 char arr[100]; cout&...

    getline函数输入要击两次回车的解决办法

    这个getline函数输入要击两次回车的解决办法不错..有点实用

    Shell高级培训

    目录 前言 显示和操作文件的实用程序 网络的实用程序 显示和修改状态的实用程序 ...用getline读取行 4.2.4.用样式对awk的行进行过滤 4.2.5.设置字段定界符 4.2.6.从awk中读取命令输出 4.2.7.在awk中使用循环 后续

    快速排序(使用vector,getline)

    对一组数据进行快速排序,使用vector进行存储数据,动态数组,需要创建一个txt文本,逐行读取getline的经典应用

Global site tag (gtag.js) - Google Analytics