2013-05-11 3 views
-2

C++ Я пытаюсь изучить класс ifstream и написал ниже код, который считывает файл Test.txtЧтение файла через GET, GetLine и читать:

'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\[email protected]@@@@@@@@@@@@@\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; 
    } 

Выход:

[email protected] /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, где, как общее число Charaters в файле 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 

Благодаря

EDIT:

Как Per Ответ получил Матса Петерсон, я попытался ниже код:

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\[email protected]@@@@@@@@@@@@@\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 Голосов По крайней мере, комментировать, что заставило вас это сделать? Я столкнулся с этой проблемой, поэтому ее попросили получить больше информации от экспертов.

+1

Вы используете Windows? –

+0

@MatsPetersson точно мое предположение :) –

+0

@MatsPetersson Да Windows 7 и использование Cygwin .. –

ответ

1

В первых двух вопросах вы говорите, что вы читаете «еще один, чем у вас есть», что является типичным следствием «отказа» состояние не установлено до тех пор, пока мы не попытаемся прочитать прошлое ». Вот почему вы должны использовать

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

как в condtions для прекращения петли - потому, что не будет выполнять цикл, когда чтение не удается.

Третья проблема заключается в том, что Windows использовала «CR + LF» для строк новой строки, где чтение файла в текстовом режиме (по умолчанию) сворачивает их в один символ новой строки. Таким образом, размер вашего файла в соответствии с is.tellg больше по одному символу для каждой новой строки, чем данные, которые вы действительно читаете. Вы можете использовать is.gcount(), чтобы узнать, сколько персонажей вы НАСТОЯТЕЛЬНО читаете. (и if (!is.read(...)) actual = is.gcount(); else actual = size; должен предоставить вам полный код).

+0

'while (is.get (buff, 50, '\ n'))' или 'while (is.getline (buff, 50, '\ n'))' производит тот же результат –

+1

Действительно? Можете ли вы отредактировать свой пост и добавить свой «новый улучшенный» код на дно, пожалуйста? Я уверен, что мой ответ верный, так что возможны два сценария: библиотека C++, которую вы используете, плоха (очень маловероятна) или что-то еще не так в вашем коде. –

0

Одна из основных причин чтения дополнительной стоимости или строки, которая называется значением для мусора (я думаю, это так) из-за использования eof (вы использовали его). когда мы использовали его, например, для чтения символа из файла, тогда он читает символ, но поскольку файл does'nt заканчивается, а цикл не заканчивается в точке, поэтому он снова считывает дополнительное значение из файла. поэтому главное, что я хочу сказать, - это избежать функции eof в любом заявлении цикла до завершения чтения файла, а не в каких-либо условиях ввода-вывода.

Смежные вопросы