Encoding.UTF8.GetString работает неправильно при получении данных из сокета - PullRequest
1 голос
/ 22 октября 2011

В эти дни я сталкиваюсь с проблемой кодирования строки из массива байтов.Я использую сокет для получения данных с сервера в буфер, затем создаю MemoryStream для чтения данных из этого буфера в tempBuffer фиксированной длины от 30 до более поздних GetString из tempBuffer.

byte tempBuff = new byte[30];
streamReader.Read(tempBuff, 0, 30);
string moTaSkill = Encoding.UTF8.GetString(tempBuff);

Я использую textBox для отображения этой строки, как показано ниже:

tbSkill.Text = moTaSkill;

В текстовом поле всегда отображается неправильно:

  1. При отладке я вижу moTaSkill = "SKill ofгерой "
  2. При отображении в текстовом поле это просто" Умение "или иногда" Умение "или" Умение "

Я пытался создать tempBuffer с длиной равнойдлина строки я получу.Но безуспешно.

Может кто-нибудь сказать мне какое-нибудь решение, чтобы это исправить?

Ответы [ 4 ]

1 голос
/ 22 октября 2011

Две проблемы. Вы забыли обратить внимание на возвращаемое значение вызова Read (). Он сообщает вам, сколько фактических байтов было скопировано в tempBuf . Что вы должны затем использовать в методе GetString (), чтобы избежать преобразования нулей.

Вторая проблема заключается в том, что TCP-соединение обеспечивает сеть поток , а не пакет. Весьма непредсказуемо, сколько байтов вы получите за каждый вызов Read (). Опять же, возвращаемое значение говорит вам об этом. Он будет соответствовать только количеству байтов, которые были переданы сервером случайно. Вы должны продолжать вызывать Read (), пока не получите их все. Главная проблема в том, что вы не обязательно знаете, когда закончится чтение. Сервер должен будет передать некоторые дополнительные данные, чтобы получатель знал. Как сначала отправить длину строки.

0 голосов
/ 22 октября 2011

Нам понадобится больше кода, но я расскажу вам, что происходит.

Ваш TextBox использует стандартные элементы управления Windows. Стандартные элементы управления Windows прекращают запись с первого \0 символа (nul в C / C ++). Это потому, что они используют "C String", которые являются массивом символов с нулевым символом в конце. Ваша строка содержит их, вероятно, потому, что вы куда-то их неправильно скопировали. Visual Studio показывает полную строку, потому что он может отображать \0 символов. Попробуйте сделать: int ix = moTaSkill.IndexOf('\0');

0 голосов
/ 22 октября 2011

Основная проблема заключается в том, что вы предполагаете, что Read заполняет ваш буфер;это не безопасно.Вы должны вызвать Read и проверить возвращаемое значение, чтобы увидеть, сколько байтов было прочитано.Все, что вам гарантировано, это <= 0 (для EOF) или> 0 и <= count (если не EOF).Это часто означает зацикливание, добавление смещения и уменьшение счетчика каждый раз.Чтобы помочь с этим, обычно указывают (сначала) длину данных, чтобы следовать, чтобы вы знали, когда остановиться.Вы также можете использовать EOF для остановки, но, очевидно, только если канал не является длительным двухсторонним диалогом. </p>

Вы также должны пытаться только кодировать реальные данные;если было прочитано 14 байтов, вы должны указать кодировщику, чтобы он смотрел только 14 байтов, даже если буфер больше.

0 голосов
/ 22 октября 2011

вы должны использовать команду flush в вашем коде, так как весь буфер должен быть сброшен.

загрузить код, где вы заполняете буфер

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...