-2

我正在尝试探索 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 收到的答复,我尝试了以下代码:

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投票至少评论是什么让你这样做?我遇到了这个问题,这就是为什么在这里要求从专家那里获得更多见解。

4

2 回答 2

1

在前两个问题中,您是因为您正在阅读“比您拥有的多一个”,这是“直到我们尝试阅读结束时才设置失败状态”的典型后果。这就是为什么你应该使用

 while(is.get(... ))
 while(is.getline(...))

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

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

于 2013-05-11T10:38:05.873 回答
0

One of the main reason of reading extra value or line which is termed as garbage value (i thinks it so) because of use of eof ( you have used it) . when we used it, for ex, to read a character from a file, then it reads the character but because file does'nt end as well loop does'nt end at point, so it again reads extra value from file. so main thing which i want to say is that avoid function eof in any looping statement untill to end the file reading and not in any input-output conditions.

于 2013-10-16T07:03:49.070 回答