Почему я не могу читать и добавлять с помощью std::fstream в Mac OS X?

Рассмотрим следующую программу на 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 ответа

Решение

Когда ты сказал:

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.

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

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

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

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

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

Другие вопросы по тегам