2013-07-29 2 views
3

Мне интересно, почему я не могу использовать оператор >>std::ifstream, чтобы читать беззнаковый int из двоичного файла.Почему fstream.read работает, а не >>?

#include <fstream> 

    int main(int argc, char* argv[]) 
    { 
     std::ifstream in(argv[1]); 
     if(in.fail()) 
      return -1; 

     unsigned int atom_size = 0; 

     in.read(reinterpret_cast<char*>(&atom_size), 4); 
     in >> atom_size; 

     return 0; 
    } 

Когда я использую in.read я получаю значение, что я хотел, но когда я использую оператор >> моя переменная atom_size не меняется. Зачем ?

ответ

8

Видимо, вы читаете двоичный файл. Команда read буквально копирует запрошенные числа байтов из файла в память, указанную указателем, который вы указали. Оператор >> ожидает, что текст ASCII будет преобразован в целое число. Две операции просто не совпадают.

+0

Если OP читает двоичный файл, не должен быть поток открыт в двоичном режиме? – dyp

+1

@ DyP, возможно, для переносимости и строгой корректности, да. На многих системах это просто не имеет значения. Разница между текстовыми и двоичными режимами обычно связана с обработкой окончаний строк и т. Д. В простой программе OP вряд ли будет разница. –

+2

Возможно, было бы хорошо отметить, что Стандарт отличает *** Форматированные входные функции *** и что 'operator >> (unsigned int & val);' является одним из них, тогда как 'get',' ignore' и 'read' являются *** Неформатированные функции ввода ***. Естественно, * Форматированная входная функция * не работает без форматированного ввода. –

3

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

>> оператор читает символы, поэтому, когда он видит, 00110101, это предполагает, что это иероглиф 5. Если вы пытаетесь читать в int, тогда >> будет правильно преобразовывать это значение в 00000101 и сохранить это значение в int. Но если символ есть, например, письмо, подобное a, которое не соответствует действительному int, >> будет терпеть неудачу (оно не будет аварийно завершено, но оно вернет false).

В вашем бинарном файле, например, может быть число 5 хранилась в 00000101, но >> считает, что он должен читать это как характер (который является символом ENQ). Это не может быть преобразовано в int, поэтому строка in >> atom_size; будет терпеть неудачу. На самом деле, она возвращает istream&, который может быть преобразован в bool, так что вы можете проверить, если он не так:

if(!(in >> atom_size)) { 
    cout << "Failed to read into atom_size" << endl; 
} 
+0

Фактически, он возвращает ссылку на поток, который имеет явное преобразование в bool, чтобы вы могли проверить, не сработало ли оно Если 'operator >>' возвратил 'bool', тогда вы не могли бы сказать' cin >> a >> b >> c' –

+0

@BenVoigt Абсолютно, спасибо, что указали это. Немного изменилось мое описание, чтобы принять это в account – maditya

+0

Отформатированная функция ввода - это форматированная входная функция независимо от того, находится ли поток в двоичном или текстовом режиме. Он все равно будет использовать средство num_get для локали, чтобы читать и преобразовывать номер, который для большинства компиляторов с по умолчанию C locale будет делать ASCII текст -> преобразование 'int'. – dyp