Почему я не могу читать и добавлять с помощью std :: fstream в Mac OS X? - PullRequest
2 голосов
/ 21 февраля 2010

Рассмотрим следующую программу на C ++, которая берет файл и печатает каждую строку. Это фрагмент более крупной программы, куда я позже добавляю файл, основываясь на том, что вижу.

#include <fstream>
using std::fstream;
#include <iostream>
#include <string>
using std::string;

int main()
{
 fstream file("file.txt", fstream::in | fstream::out | fstream::app);

 string line;
 while (std::getline(file, line))
  std::cerr << line << std::endl;

 return 0;
}

Теперь примените эту версию file.txt (одно слово в первой строке, за которым следует новая строка):

Rain

На моей машине (Snow Leopard) это ничего не печатает. При ближайшем рассмотрении первый вызов getline завершается неудачно. Странно, но и если я добавлю вторую строку, ничего не получится!

Может кто-нибудь разгадать эту тайну?

Ответы [ 2 ]

9 голосов
/ 21 февраля 2010

Когда вы говорите:

fstream file("file.txt", fstream::in | fstream::out | fstream::app);

вы открываете файл в режиме добавления - то есть в конце. Просто откройте его в режиме чтения:

fstream file("file.txt", fstream::in );

или используйте ifstream:

ifstream file("file.txt" );

И, конечно, как предлагает Уорвикер, вы всегда должны проверять, что открытие прошло успешно.

Если вы решили открыть в режиме добавления, вы можете явно переместить указатель чтения:

#include <fstream>
#include <iostream>
#include <string>
using namespace std;

int main() {
    fstream file( "afile.txt", ios::in | ios::out | ios::app );
    if ( ! file.is_open()  ) {
        cerr << "open failed" << endl;
        return 1;
    }
    else {
        file.seekg( 0, ios::beg );   // move read pointer
        string line;
        while( getline( file, line ) ) {
            cout << line << endl;
        }
    }
}

Редактировать: Кажется, что сочетание флагов, используемых при открытии файла, приводит к специфическому поведению реализации. Приведенный выше код работает с g ++ в Windows, но не с g ++ в Linux.

2 голосов
/ 21 февраля 2010

Вы должны проверить, был ли файл действительно открыт:

if (!file)
    std::cerr << "Oh dear" << std::endl;

Обновление: фактически файл, вероятно, был открыт, но находится в режиме добавления - см. Ответ Neii.

Обновление 2: хорошо, снова не так. По крайней мере, в Leopard g ++ файл не будет открыт, потому что флаг app несовместим с флагом in. Таким образом, вышеупомянутая проверка напечатает Oh dear.

В MSVC ++ он идет вперед и открывает файл, очевидно, с позиции чтения в начале, что объясняет, почему другие люди видели, как это работает, и я прошу прощения за сомнение в их правдивости!

...