Зачем использовать беззнаковые символы для записи в двоичные файлы?И почему нельзя использовать потоковые операторы для записи в двоичные файлы? - PullRequest
0 голосов
/ 18 сентября 2011

Мой первый вопрос: почему для записи в файлы в двоичном режиме принято использовать беззнаковые символы?Во всех примерах, которые я видел, любое другое числовое значение преобразуется в unsigned char перед записью в двоичный файл.

Мой второй вопрос: что плохого в использовании потоковых операторов для записи в двоичные файлы?Я слышал, что операторы read () и write () лучше всего использовать для записи в двоичные файлы, но я не совсем понимаю, почему это так.Использование потоковых операторов для записи в двоичные файлы прекрасно работает, если я сначала приведу значение к unsigned char.

float num = 500.5;
ostream file("file.txt", ios::binary);

file << num  // results in gibberish when I try to read the file later
file << (unsigned char)num  // no problems reading the file with stream operators

Заранее спасибо.

Ответы [ 3 ]

3 голосов
/ 18 сентября 2011

chars - самый маленький тип в C / C ++ (по определению, sizeof( char ) == 1). Это обычный способ видеть объекты как последовательность байтов. unsigned используется, чтобы не мешать знаковой арифметике и потому что она лучше всего представляет двоичное содержимое (значение от 0 до 255).

Для работы с двоичными файлами потоки предоставляют функции read и write. Функции вставки и извлечения отформатированы. Он работает для вас просто случайно, например, если вы выведите целое число с помощью <<, тогда он фактически выведет текстовое представление целочисленного значения, а не его двоичное представление. В представленном вами примере вы приводите float к unsigned char перед выводом, фактически приводя реальное значение к маленькому целому числу. Что вы получаете, когда вы пытаетесь прочитать float обратно из файла? </p>

2 голосов
/ 18 сентября 2011

Поскольку все перегрузки operator<< называются отформатированными функциями. Они форматируют данные перед записью в выходной файл. Другими словами, их нельзя использовать, если вы хотите записать двоичные данные в файл. Двоичные данные могут быть записаны в файл с неотформатированными функциями - теми, которые не форматируют данные.

std::ostream предоставляет одну неотформатированную функцию вывода с именем write() со следующей подписью:

ostream& write ( const char* s , streamsize n );

, который также отвечает на другой вопрос:

Почему для записи в файлы в двоичном режиме принято использовать беззнаковые символы?

Нет. Это неверно. Функция write() принимает const char*, а не const unsigned char *.

-

В онлайн документе говорится о operator<<:

Этот оператор (<<), применяемый к выходному потоку, называется оператором вставки. Он выполняет операцию вывода в потоке, обычно <strong>, включая некоторое форматирование данных (как, например, запись числового значения в виде последовательности символов).

и это говорит о write():

Это неформатированная функция вывода , и то, что записывается, не обязательно является строкой c, поэтому любой нулевой символ, найденный в массиве s, копируется в место назначения и не завершает процесс записи.

1 голос
/ 18 сентября 2011

Причина использования unsigned char заключается в том, что он гарантированно равен unsigned, что очень желательно, когда речь идет о побитовых операциях - что может пригодиться при манипулировании двоичными данными. Следует помнить, что char (также известный как обычный char) является отдельным типом от unsigned char, и не указано, является ли это типом со знаком или без знака.

Наконец, отформатированные функции потоков предназначены для вывода / анализа текстового , удобочитаемого представления данных, где, например, 123456789 может 1 представляется в виде девяти символов "123456789", которые могут вмещаться в девять байтов. Для сравнения, возможное двоичное представление в виде 0x75BCD15 может уместиться в четыре байта, что более чем в два раза компактнее.

Не совсем неожиданно, что то, что вы делаете, успешно, так как то, является ли что-то двоичным файлом или нет, просто определяется тем, что вы делаете с ним. Если вы пишете текст в файл, это нормально, чтобы восстановить этот текст позже.

1 : в зависимости от, например, locales, что является еще одной функцией, специфичной для отформатированных функций.

...