2009-02-17 4 views
3

В нашем API мы используем byte [] для передачи данных по сети. Все работало нормально, до того дня, когда наши «иностранные» клиенты решили передать/получить символы Юникода.Преобразование символа юникода из байта

Насколько я знаю, символы Unicode занимают 2 байта, однако мы выделяем только 1 байт в массиве байтов.

Вот как мы читаем символ из байт [] массив:

 // buffer is a byte[6553] and index is a current location in the buffer 
     char c = System.BitConverter.ToChar(buffer, m_index); 
     index += SIZEOF_BYTE; 

     return c; 

Так текущий вопрос является API получает странный характер Unicode, когда я смотрю на шестнадцатеричное Unicode. Я обнаружил, что последний значащий байт правильный, но самый старший байт имеет значение, когда он должен быть 0. Быстрое обходное решение, до сих пор, было 0x00FF & c для фильтрации msb.

Просьба предложить правильный подход к работе с символами Unicode, поступающими из сокета?

Спасибо.

Solution:

Престижность Jon:

символ с = (символ) буфере [m_index];

И, как он упомянул, причина, по которой он работает, заключается в том, что клиент api получает символ, занимающий только один байт, а BitConverter.ToChar использует два, следовательно, проблему в его преобразовании. Я все еще удивляюсь, почему это сработало для некоторого набора персонажей, а не для других, поскольку это должно было провалиться во всех случаях.

Спасибо, ребята, отличные ответы!

+1

«Насколько я знаю, символы Unicode занимают 2 байта», это неправильно. лучшее упрощение - думать, что «ASCII устарел, текстовые потоки являются UTF8» и, следовательно, всегда делают некоторые кодировки/декодирования, чтобы преобразовывать внутреннее в/из UTF8 в любое время, когда вы их вынимаете/в свое приложение. – Javier

+1

Это упрощение неверно, так как оно предполагает UTF-8 всюду - это, конечно же, не так. Да, UTF-8 очень распространен, но если предположить, что это повсеместно, это ошибка. Лучше всего не упрощать: вы всегда должны знать кодировку при кодировании/декодировании. Не предполагайте. –

+0

В этом случае я не предполагаю, что посмотрел на код на стороне сервера и увидел, что он действительно отправляет символ, упакованный в 1 байт (без какой-либо кодировки). Тем не менее, я согласен с тем, что правильное кодирование должно быть исследовано до кодирования/декодирования. Спасибо – 2009-02-18 18:28:46

ответ

5

Вы должны использовать Encoding.GetString, используя наиболее подходящую кодировку.

Я не совсем понимаю вашу ситуацию полностью, но класс Encoding почти наверняка будет способом справиться с этим.

Кто контролирует данные здесь? Ваш код или код ваших клиентов? Вы определили, что такое правильный формат?

EDIT: Хорошо, я еще раз посмотрел на ваш код: BitConverter.ToChar возвращает «Символ, образованный двумя байтами, начиная с startIndex». Если вы хотите использовать только один байт, просто бросьте:

char c = (char) buffer[m_index]; 

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

+0

Это может быть немного сложнее, так как мы также получаем строки из сети через str = System.Text.ASCIIEncoding.ASCII.GetString(). Возможно, я не понимаю вас. Не могли бы вы указать мне на это пример. Спасибо – 2009-02-17 14:47:29

+0

Если вы используете Encoding.ASCII, вы не сможете обрабатывать любые символы с акцентом. Я предлагаю вам предоставить дополнительную информацию в вопросе. –

0

Вы должны посмотреть на функцию System.Text.ASCIIEncoder.ASCII.GetString, которая принимает массив byte [] и преобразует ее в строку (для ascii).

И System.Text.UTF8Encoder или System.Text.UTF16Encoder для строк Unicode в кодировках UTF8 или UTF16.

Существуют также функции преобразования строк в байт [] в классы ASCIIEncoding, UTF8Encoding и UTF16Encoding: см. Функции GetBytes (String).

0

Unicode символы могут принимать до четырех байтов, но редко являются сообщениями, закодированными в проводе, с использованием 4 байтов для каждого символа. Скорее, используются такие схемы, как UTF8 или UTF16, которые при необходимости вводят дополнительные байты.

Посмотрите на руководство по эксплуатации Encoding.

0

Тестовые потоки должны содержать byte-order marker, которые позволят вам определить, как обрабатывать двоичные данные.

0

Непонятно, что именно ваша цель здесь. Из того, что я могу сказать, есть 2 пути, которые вы можете взять

  1. Игнорировать все данные, передаваемые в Unicode
  2. процесса как Юникод и ASCII строки

ИМХО, # 1 это путь , Но похоже, что ваш протокол не обязательно настроен на работу с строкой unicode. Вам нужно будет сделать некоторую логику обнаружения, чтобы определить, входит ли строка в версию Unicode. Если это, вы можете использовать метод Enconding.Unicode.GetString для преобразования этого конкретного массива байтов.

0

Какую кодировку используете ваши клиенты? Если некоторые из ваших клиентов все еще используют ASCII, вам понадобятся, чтобы ваши международные клиенты использовали что-то, что отображает набор ASCII (1-127) для себя, например UTF8. После этого используйте метод GetString в кодировке UTF8.

0

Мое единственное решение - исправить API. Либо сообщите пользователям использовать только строку ASCII в байте [] или исправить ее для поддержки ASCII и любой другой кодировки, которую вам нужно использовать.

Решение о том, какая кодировка предоставляется иностранными клиентами только из байт [], может быть немного сложной.

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