Чтение файла по байтам

У меня есть простая программа:

#include <cstring>
#include <fstream>

using namespace std;

int main(int argc, char **argv)
{
    cout << "Creating test.txt file..." << endl;

    // Writing to file
    fstream fWrite;
    fWrite.open("./_test_data/test.txt", fstream::out | fstream::trunc);
    if (fWrite.fail()) {
        cout << "Creating test.txt file failed!" << endl;
        fWrite.close();
    } else {
        fWrite << (char) 0x09 << (char) 0x0A << (char) 0x0B;
        fWrite << (char) 0x0C << (char) 0x0D << (char) 0x0E;
        fWrite << flush;

        fWrite.close();
        cout << "test.txt file successfully created." << endl;
    }

    // Reading created file
    cout << "Reading test.txt file..." << endl;
    fstream fRead;
    fRead.open("./_test_data/test.txt", fstream::in);
    if (fRead.fail()) {
        fRead.close();
    } else {
        char character;

        while (true) {
            fRead >> character;

            if (fRead.eof()) {
                cout << (int)character << endl;
                cout << "EOF detected!" << endl;
                break;
            }

            cout << (int)character << endl;
        }
        fRead.close();
    }

    return 0;
}

Он должен просто записывать байты в порядке 09 0A 0B 0C 0D 0E, что сделано нормально (проверено шестнадцатеричным дампом), но при чтении того же файла он читает первый байт как 0E (= 14 в десятичной системе), а затем приходит EOF...

Creating test.txt file...
test.txt file successfully created.
Reading test.txt file...
14
14
EOF detected!

Почему?


person Radek Simko    schedule 18.03.2011    source источник


Ответы (3)


Используйте fRead.read(&character,1) вместо fRead >> character.

Но вы также можете удалить cout << (int)character << endl; в операторе if.

person BenjaminB    schedule 18.03.2011

Откройте файл в двоичном режиме: fRead.open("...", fstream::in | fstream::binary); — это необходимо, чтобы слой файла не переводил последовательности новой строки.

person Alexander Gessler    schedule 18.03.2011
comment
Этот ответ необходим, но недостаточен. В дополнение к открытию в двоичном режиме OP должен либо использовать noskipws, либо избегать оператора извлечения. - person Robᵩ; 19.03.2011

Попробуйте fRead >> std::noskipws. Оператор >> в потоках чтения пропускает пробелы, чтобы перейти к следующим «интересным» данным. Рассмотрим входной поток, например hi there. Читая, что std::string за раз, вы получите hi и there, при этом пробел игнорируется. Точно так же, читая это посимвольно, вы получаете -h-i-t-h-e-r-e-, а символ пробела игнорируется.

Все байты, которые вы не могли прочитать из fRead, считались пустым пространством, поэтому все они игнорировались.

Причина, по которой fRead.read() является решением (и хорошим), заключается в том, что он выполняет неформатированный ввод — он не заботится о пробелах.

Наконец, вы должны внести следующие изменения в свою программу:

#include <iostream>  // you need this for std::cout and std::endl

Вам нужно iostream для std::cout и std::endl.

fRead.open("./_test_data/test.txt", fstream::in | fstream::binary);

Вам нужно открыть тестовый файл в двоичном формате (как для записи, так и для чтения), если в нем будут какие-либо непечатаемые символы.

person Robᵩ    schedule 18.03.2011