2009-12-02 3 views
8

У меня есть код, который управляет двоичными файлами с помощью fstream с установленным двоичным флагом и использованием функций и функций неформатированного ввода-вывода. Это работает правильно во всех системах, которые я когда-либо использовал (биты в файле точно так, как ожидалось), но это в основном все английские. Я задавался вопросом о возможности изменения этих байтов с помощью кодека в другой системе.Запись двоичных файлов с использованием C++: имеет ли значение по умолчанию значение языка по умолчанию?

Похоже, что стандарт говорит, что использование неформатированного ввода-вывода ведет себя так же, как вставлять символы в streambuf с помощью sputc/sgetc. Они вызовут функции переполнения или underflow в вызове streambuf, и похоже, что это приводит к тому, что содержимое проходит через некоторый codecvt (например, см. 27.8.1.4.3 в стандарте C++). Для basic_filebuf создание этого кодека указано в 27.8.1.1.5. Это делает его похожим на то, что результаты будут зависеть от того, что возвращает base_filebuf.getloc().

Итак, могу ли я предположить, что массив символов, выписанный с использованием ofstream.write в одной системе, может быть восстановлен дословно с использованием ifstream.read в другой системе, независимо от того, какую конфигурацию локали может использовать любой пользователь на своих система? Я хотел бы сделать следующие предположения:

  1. Программа использует по умолчанию локали (то есть, программа не изменения параметров языка сама на всех).
  2. Системы имеют CHAR_BIT 8, имеют один и тот же порядок бит в каждом байте, хранят файлы в виде октетов и т. Д.
  3. Объекты потока имеют бинарный флаг.
  4. Нам не нужно беспокоиться о каких-либо различиях на этой стадии. Если любые байты в массиве должны интерпретироваться как многобайтовое значение, конверсии endianess будут обрабатываться по мере необходимости на более позднем этапе.

Если языковой стандарт по умолчанию не может пройти через этот материал без изменений в какой-либо конфигурации системы (я не знаю, арабский или что-то еще), тогда как лучше всего писать двоичные файлы с помощью C++?

+1

Я думаю, вы должны добавить тот же порядок байтов к своему предположению. Или я полностью оттуда? –

+0

@ TheScottMachine: Space_C0wb0y прав, добавьте тот же порядок байтов к вашим предположениям – Stan

+0

Спасибо, я добавил дополнительное предположение, чтобы уточнить. – TheScottMachine

ответ

0

В Windows это должно быть хорошо, но на другой ОС вы также должны проверить окончания строки (точно так же, как и безопасность). По умолчанию C/C++ - это «C», который не в зависимости от локали системы.

Это не гарантия. Как вы знаете, компилятор C/C++ и их целевые машины сильно различаются. Поэтому вы ждете неприятностей, если будете придерживаться всех этих предположений. Незначительные накладные расходы для изменения языкового стандарта, если вы не попытаетесь сделать это сотни раз в секунду.

+0

Спасибо, информация о стандартном стандарте - это то, что я искал. Я думаю, что окончание строк не должно иметь значения, пока в потоке установлен двоичный флаг. – TheScottMachine

1

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

Еще одна вещь: есть возможность поломки в разных местах. Если, например, ваш источник данных создал двоичные данные на основе языкового стандарта (и формат этих данных изменился бы в зависимости от языка - это плохая идея кстати). Это может вызвать проблемы при загрузке данных на машинах с разными языками. Это ошибка дизайна.

Если вы используете стандартные типы данных/структуры, которые имеют одинаковый формат и расположение независимо от того, какой язык они были созданы, все должно быть в порядке.

1

Спасибо за помощь. Я просто подумал, что может быть полезно опубликовать дополнительную информацию об этом, которая не вписывается в комментарий.

Языковой стандарт по умолчанию для программ на С ++ всегда является языковой версией «C» (http://www.cplusplus.com/reference/clibrary/clocale/setlocale/). Если это единственная локаль, используемая в вашей программе, это означает, что поведение не зависит от конкретной конфигурации локали машины, на которой он работает. Это также означает, что неформатированный ввод-вывод для символа не претерпевает никакого преобразования кода (wchar_t может быть другой историей). Это означает, что (учитывая предположения в вопросе) чтение и запись должны позволять восстанавливать двоичные данные без изменений.

(из документации) Вы можете глобально установить локаль приложения в соответствии с системным значением по умолчанию, вызвав setlocale (LC_ALL, ""), что будет означать, что потоки, созданные из этой точки, будут использовать локаль по умолчанию для системы. Чтобы вернуть его в локаль «C», вы можете вызвать setlocale (LC_ALL, «C»), что будет означать, что будут использоваться потоки, построенные в будущем. Вы также можете указать, что локальный «C» должен использоваться для потока, который уже сконструирован вызовом stream.imbue (locale :: classic()).

Смежные вопросы