C # big-endian UCS-2 - PullRequest
       36

C # big-endian UCS-2

2 голосов
/ 07 августа 2011

Проект, над которым я сейчас работаю, должен взаимодействовать с клиентской системой, которую мы не делаем, поэтому у нас нет контроля над тем, как данные отправляются в любом случае. Проблема в том, что работали в C #, который, похоже, не поддерживает UCS-2 и очень мало поддерживает big-endian. (насколько я могу судить)

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

Но спасибо за ваше время в любом случае.

EDIT: BigEndianUnicode работает для правильного декодирования строки, проблема заключалась в получении других данных с прямым порядком байтов, поэтому пока использование IPAddress.HostToNetworkOrder (), как это было предложено в другом месте, позволило мне декодировать половину строки (Merli? Is что подходит и должно быть Merlin33069)

Я прочесываю короткий код, чтобы увидеть, пропустила ли я еще одну переменную длины

РЕШЕНИЕ: после выяснения, что бигендиановые переменные были главной проблемой, я вернулся и рассмотрел детали, и кажется, что длина строк отправлялась в счетчиках символов, а не в байтах (в utf казалось бы, что char равен двум байтам) все, что мне нужно было сделать, это удвоить его, и это сработало. спасибо всем за помощь.

Ответы [ 3 ]

2 голосов
/ 07 августа 2011
string x = "abc";
byte[] data = Encoding.BigEndianUnicode.GetBytes(x);

В другом направлении:

string decodedX = Encoding.BigEndianUnicode.GetString(data);

Это не точно UCS-2 , но этого достаточно для большинства случаев.

UPD: FAQ по Unicode

В: В чем разница между UCS-2 и UTF-16?

A: UCS-2 является устаревшей терминологией, которая относится к Unicode реализация до Unicode 1.1, до суррогатных кодовых точек и UTF-16 были добавлены в версию 2.0 стандарта. Этот термин должен сейчас следует избегать.

UCS-2 не определяет отдельный формат данных, потому что UTF-16 и UCS-2 идентичны для целей обмена данными. Оба 16-битные, и имеют точно такое же представление кодовой единицы.

Иногда в прошлом реализация была помечена как "UCS-2" для указать, что он не поддерживает дополнительные символы и не поддерживает интерпретировать пары суррогатных кодовых точек как символы. Такой реализация не будет обрабатывать обработку свойств символов, границы кодовых точек, сопоставление и т. д. для дополнительных символов.

2 голосов
/ 07 августа 2011

EDIT: теперь мы знаем, что проблема не в кодировке текстовых данных , а в кодировке length .Есть несколько вариантов:

  • Поменять местами байты и затем использовать встроенный код BitConverter (который, как я полагаю, используется сейчас; это или BinaryReader)
  • Выполните преобразование самостоятельно, используя повторяющиеся операции «добавления и сдвига»
  • Используйте мои EndianBitConverter или EndianBinaryReader классы из MiscUtil , которые похожи на BitConverter и BinaryReader, но позвольте вам указать порядковый номер.

Возможно, вы ищете Encoding.BigEndianUnicode.Это кодировка UTF-16 с прямым порядком байтов, которая строго не совпадает с кодировкой UCS-2 (как указано Марком), но должна подойти, если вы не передадите ей строки, содержащие символы вне BMP (то есть выше U + FFFF), которые не могут быть представлены в UCS-2, но представлены в UTF-16.

Со страницы Википедии :

Более старый UCS-2 (2-байтовый универсальный набор символов) представляет собой аналогичную кодировку символов, которая была заменена UTF-16 в версии 2.0 стандарта Unicode в июле 1996 года. 2 Он производит фиксированную длинуформатировать, просто используя кодовую точку в качестве 16-битной кодовой единицы и получая точно такой же результат, как UTF-16, для 96,9% всех кодовых точек в диапазоне 0-0xFFFF, включая все символы, которым было присвоено значение при этомвремя.

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

1 голос
/ 07 августа 2011

UCS-2 настолько близок к UTF-16, что Encoding.BigEndianUnicode будет почти всегда достаточно.

Проблема (комментарии), связанная с чтением префикса длины (как big-endian), более корректно решается с помощью операций сдвига, которые будут работать правильно во всех системах. Например:

Read4BytesIntoBuffer(buffer);
int len =(buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | (buffer[3]); 

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

...