通过get,getline和read读取文件:C ++

时间:2013-05-11 10:29:37

标签: c++ ifstream

我正在尝试探索ifstream类并编写下面的代码来读取文件Test.txt

'Test.txt' - 内容

This is Line One
This is Line Two
This is Line Three
This is Line Four
This is Line Five

代码编写:

#include <iostream>
#include <fstream>
#include <limits>

using namespace std;

int main()
{

    char buff[50];

    char ch;
    ifstream is("test.txt");
    if (!is)
    cout << "Unable to open " << endl;

    while(is)
    {
        ch=(char)is.get();
        if(ch != EOF)//If EOF is not checked then
        //EOF converted as a char is displyed as
        // last char of the file
        cout << ch;
        }


    cout << "\n\n###########\n\n";
    is.clear(); //clearing ios_base::eofbit which was set 
    //in previous action
    is.seekg(0,ios_base::beg); //Going back to start of File

   while(is)
   {

     is.get(buff,50,'\n');
     cout << buff ;
     cout << "\n--------------\n";
     is.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
     //Flushing the is stream as '\n' was left by get fn
   }


  cout << "\n\n@@@@@@@@@@@@@@\n\n";
    is.clear();
    is.seekg(0,ios_base::beg);

    while(!is.eof())
    {
        is.getline(buff,50,'\n');
        cout << buff;
        cout << "\n--------------\n";
        //No need to flush the is stream as '\n' 
        //was extracted and discarded by getline
        }

    cout << "\n\n$$$$$$$$$$$$$$\n\n";
    is.clear();
    is.seekg(0,ios_base::end);
    int size=is.tellg();
    is.seekg(0,ios_base::beg);
    cout << "size : " << size << endl;

    //char* readBuff = (char *) ::operator new(sizeof(char)*size);
    char* readBuff = new char[size];
    is.read(readBuff,size);
    cout << readBuff;
    delete(readBuff);

    is.close();

    return 0;
    }

输出:

Gaurav@Gaurav-PC /cygdrive/d/Trial
$ ./Trial
This is Line One
This is Line Two
This is Line Three
This is Line Four
This is Line Five

###########

This is Line One
--------------
This is Line Two
--------------
This is Line Three
--------------
This is Line Four
--------------
This is Line Five
--------------


@@@@@@@@@@@@@@

This is Line One
--------------
This is Line Two
--------------
This is Line Three
--------------
This is Line Four
--------------
This is Line Five
--------------


$$$$$$$$$$$$$$

size : 92
This is Line One
This is Line Two
This is Line Three
This is Line Four
This is Line Five▒u

我想问一些问题并澄清:

1)当我使用get如下

   while(is)
   {

     is.get(buff,50,'\n');
     cout << buff ;
    // cout << "\n--------------\n";
     is.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
     //Flushing the is stream as '\n' was left by get fn
   }

即。我注释掉了cout << "\n--------------\n";,然后将文件读作

###########

This is Line Fivee

即。它错过了前四行,只读了最后一行'e' ..但是不知道为什么会这样?

2)当我使用getline时,如下所示:

// while(!is.eof())
   while(is)
    {
        is.getline(buff,50,'\n');
        cout << buff;
        cout << "\n--------------\n";
        //No need to flush the is stream as '\n'
        //was extracted and discarded by getline
        }

即。我使用了while(is)而不是while(!is.eof()) - 我得到了输出:

@@@@@@@@@@@@@@

This is Line One
--------------
This is Line Two
--------------
This is Line Three
--------------
This is Line Four
--------------
This is Line Five
--------------

--------------

即。在最后一行之后,我得到两条额外的线。再也无法弄清楚为什么会这样?

3)使用read函数,我得到的尺寸是92,其中文件中的字符总数为89,包括EOF },spaces'\n'。最后一行在显示文件的最后一个字符后显示两个垃圾字符。为什么会这样?

cout << "\n\n$$$$$$$$$$$$$$\n\n";
is.clear();
is.seekg(0,ios_base::end);
int size=is.tellg();
is.seekg(0,ios_base::beg);
cout << "size : " << size << endl;

//char* readBuff = (char *) ::operator new(sizeof(char)*size);
char* readBuff = new char[size];
is.read(readBuff,size);
cout << readBuff;
delete(readBuff);

输出:

$$$$$$$$$$$$$$

size : 92
This is Line One
This is Line Two
This is Line Three
This is Line Four
This is Line Five▒u

由于

修改

根据Mats Peterson收到的Per Answer,我尝试了以下代码:

while(is.get(buff,50,'\n'))
   {
     cout << buff ;
     //cout << "\n--------------\n";
     is.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
     //Flushing the is stream as '\n' was left by get fn
   }


  cout << "\n\n@@@@@@@@@@@@@@\n\n";
    is.clear();
    is.seekg(0,ios_base::beg);

   // while(!is.eof())
   while(is.getline(buff,50,'\n'))
    {

        cout << buff;
        //cout << "\n--------------\n";
        //No need to flush the is stream as '\n'
        //was extracted and discarded by getline
        }

但得到了输出:

###########

This is Line Fivee

@@@@@@@@@@@@@@

This is Line Fivee

即只有最后一行读取...如果我取消注释//cout << "\n--------------\n";我得到正确的阅读

@Down Votes 至少评论是什么让你这样做的?我遇到了这个问题,这就是为什么要求专家提供更多见解的原因。

2 个答案:

答案 0 :(得分:1)

在前两个问题中,你是因为你正在阅读“比你有更多的”,这是“在我们试图阅读结束之前未设置失败状态”的典型结果。这就是你应该使用

的原因
 while(is.get(... ))
 while(is.getline(...))

作为结束循环的条件 - 因为当读取失败时不会运行循环。

第三个问题是因为Windows使用“CR + LF”作为换行符,其中以文本模式(默认值)读取文件会将这些文件折叠为单个换行符。因此,根据is.tellg的文件大小,每个换行符的大小比实际读取的数据大一个字符。您可以使用is.gcount()查看您实际阅读的字符数。 (而if (!is.read(... )) actual = is.gcount(); else actual = size;应该会给你一整段代码)。

答案 1 :(得分:0)

由于使用了eof(你已经使用过它),读取额外值或线的一个主要原因被称为垃圾值(我认为是这样)。当我们使用它时,例如,从文件中读取一个字符,然后它读取字符,但因为文件没有结束,循环也没有在点结束,所以它再次从文件中读取额外的值。所以我要说的主要是避免在任何循环语句中使用函数eof,直到结束文件读取而不是在任何输入输出条件下。