Преобразование содержимого байтового массива в wchar_t *

Кажется, у меня возникла проблема с преобразованием байтового массива (содержащего текст из текстового документа) в объект LPTSTR (wchar_t *). Каждый раз, когда код выполняется, я получаю кучу ненужных символов Unicode.

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

Первое, что происходит, когда мы вызываем код на C #, чтобы открыть Microsoft Word и преобразовать текст в документе в байтовый массив.

byte document __gc[];
document = word->ConvertToArray(filename);

Содержание документа следующее:

{84, 101, 115, 116, 32, 68, 111, 99, 117, 109, 101, 110, 116, 13, 10}

В результате получается следующая строка: «Тестовый документ».

Наш следующий шаг — выделить память для хранения байтового массива в переменной LPTSTR,

byte __pin * value;

value = &document[0];

LPTSTR image;
image = (LPTSTR)malloc( document->Length + 1 );

Как только мы выполняем строку, где мы начинаем выделять память, наша переменная изображения заполняется кучей нежелательных символов Unicode:

췍췍췍췍췍췍췍췍﷽﷽����˿於潁

И затем мы делаем memcpy для передачи по всем данным

memcpy(image,value,document->Length);

Что приводит к появлению большего количества нежелательных символов Unicode:

敔瑳䐠捯浵湥൴촊﷽﷽����˿於潁

Я полагаю, что проблема, с которой мы сталкиваемся, связана либо с тем, как мы храним значения в байтовом массиве, либо, возможно, когда мы копируем данные из байтового массива в переменную LPTSTR. Будем весьма благодарны за любую помощь в объяснении того, что я делаю неправильно или что-либо, чтобы указать мне правильное направление.

1

Решение

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

byte это просто typedef или что-то для char или же unsigned char, Таким образом, байтовый массив использует некоторые char кодировка для строки. Вам действительно нужно конвертировать из этой кодировки, какой бы она ни была, в UTF-16 для Windows ‘ wchar_t, Вот типичный метод, рекомендуемый для таких преобразований в Windows:

int output_size = MultiByteToWideChar(CP_ACP,0,value,-1,NULL,0);
assert(0<output_size);
wchar_t *converted_buf = new wchar_t[output_size];
int size = MultiByteToWideChar(CP_ACP,0,value,-1,converted_buf,output_size);
assert(output_size==size);

Мы называем функцию MultiByteToWideChar() дважды, один раз, чтобы выяснить, какой размер буфера необходим для хранения результата преобразования, и второй раз, передав буфер, который мы распределили, для фактического преобразования.

CP_ACP задает исходную кодировку, и вам нужно проверить документацию API, чтобы выяснить, каково это значение на самом деле. CP_ACP расшифровывается как «кодовая страница: кодовая страница Ansi», что является способом Microsoft сказать «кодировка, установленная для программ, не поддерживающих Юникод». API может использовать что-то еще, например CP_UTF8 (мы можем надеяться) или 1252 или что-то.

Вы можете просмотреть остальную часть документации на MultiByteToWideChar Вот выяснить другие аргументы.


Как только мы выполняем строку, где мы начинаем выделять память, наша переменная изображения заполняется кучей нежелательных символов Unicode:

Когда вы звоните malloc() данная память неинициализирована и содержит только мусор. Значения, которые вы видите перед инициализацией, не имеют значения, и вам просто не следует использовать эти данные. Единственные данные, которые имеют значение, это то, чем вы заполняете буфер. MultiByteToWideChar() Приведенный выше код также автоматически завершит строку нулем, так что вы не увидите мусора в неиспользуемом буферном пространстве (и метод, который мы используем для выделения буфера, не оставит дополнительного пространства).


Приведенный выше код на самом деле не очень хороший стиль C ++. Это просто типичное использование API в стиле C, предоставляемого Win32. Способ, которым я предпочитаю делать преобразования (если я вынужден), больше похож на:

std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>,wchar_t> convert; // converter object saved somewhere

std::wstring output = convert.from_bytes(value);

(Предполагая, что char используется кодировка UTF-8. Вам придется использовать другой codecvt фасет для любой другой кодировки.)

6

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]