2017-01-23 9 views
2

Мне нужно вручную добавить спецификацию UTF-8 в простой текстовый файл. Однако я не могу написать спецификацию следующим способом. С моим довольно ограниченным знанием C++ я действительно не понимаю, что я делаю неправильно. Я предполагаю, что это должно быть связано с тем фактом, что я пишу только 3 байта - и система ожидает, что я буду писать кратные 2 по любой причине. Код скомпилирован в наборе символов Unicode. Любые подсказки, указывающие на меня в правильном направлении, приветствуются.Получение исключения при написании спецификации UTF-8

FILE* fStream; 
errno_t e = _tfopen_s(&fStream, strExportFile, TEXT("wt,ccs=UTF-8")); //UTF-8 

if (e != 0) 
{ 
    //Error Handling 
    return 0; 
} 

CStdioFile* fileo = new CStdioFile(fStream); 
fileo->SeekToBegin(); 

//Write BOM 
unsigned char bom[] = { 0xEF,0xBB,0xBF }; 
fileo->Write(bom,3); 
fileo->Flush(); //BOOM: Assertion failed buffer_size % 2 == 0 
+0

Я не совсем понимаю ваш вопрос. Из документации [_tfopen_s] (https://msdn.microsoft.com/en-us/library/z5hh6ee9.aspx): * «Файлы, открытые для записи в режиме Unicode, автоматически присваиваются спецификации.» * открывают файл для записи, и вы включаете режим Unicode, поэтому нет необходимости вручную записывать спецификацию вручную. – IInspectable

+0

@Inpectpectable Я согласен с тем, что это упоминание в документации - однако я никогда не испытывал, что спецификация автоматически записывается при использовании строк кода выше. – Marwie

ответ

2

В соответствии с Microsoft's documentation for _tfopen_s (подчеркивание добавлено):

Когда функция Юникода в поток ввода/вывода работает в текстовом режиме (по умолчанию), предполагается, что поток источника или назначения, чтобы последовательность многобайтовых символов. Таким образом, функции ввода-вывода Unicode преобразуют многобайтовые символы в широкие символы (как если бы вызов функции mbtowc). По той же причине функции потока-вывода Unicode преобразуют широкие символы в многобайтовые символы (как если бы вызов функции wctomb).

Вы обязаны написать UTF-16 символов в файл, который затем будет переведен . Вместо 3-байтовой последовательности 0xEF,0xBB,0xBF вам нужно написать один 16-разрядный 0xfeff.

+0

Вы абсолютно правы - замените на 'unsigned char bom [] = {0xff, 0xfe};' и запись 2 байта исправила проблему. Обратите внимание, что мне пришлось обменивать порядок 0xfe и 0xff при хранении в массиве. Любые идеи почему? Спасибо, что указали мой нос на правый абзац в документации ;-) – Marwie

+1

@Marwie вам нужно поменять байты, потому что [x86-процессоры мало endian] (http://stackoverflow.com/questions/5185551/why-is- x86-прямой порядок байтов). Если вы написали 'uint16_t' или' wchar_t', вам не нужно будет беспокоиться об этом - байты уже будут заменены в памяти. –