C# BinaryReader.ReadChar выдает System.ArgumentException: буфер выходных символов слишком мал при чтении NetworkStream

При чтении C# NetworkStream (из TCP-сокета потокового типа) BinaryReader.ReadChar иногда выдает исключения System.ArgumentException: The output char buffer is too small to contain the decoded characters, encoding 'Unicode (UTF-8)'

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

И что совсем обескураживает:

  • Исключение не возникает при использовании точки останова и пошаговом обходе строки с вызовом ReadChar

  • Исключение не возникает, если ReadChar предшествует Thread.Sleep(1000) (но все же может возникать с меньшими тайм-аутами).

  • Исключение не возникает при использовании BinaryReader на FileStream, где хранятся все точные байты ответа TCP-сервера.

Итак, в чем может быть проблема, связанная со временем, при буферизации отдельных символов из потока сокета?


person user2732454    schedule 30.08.2013    source источник


Ответы (2)


У меня тоже была эта проблема. И вот несколько фактов об этом:

  1. Известно, что System.ArgumentException: The output char buffer is too small to contain the decoded characters, encoding 'Unicode (UTF-8)' связан с проблемой кодировки UTF-8 (неверный код символа), а не с проблемой буферизации - Подробности здесь

  2. Известно, что NetworkStream (Read и другие методы) возвращает только то количество байтов, которое уже присутствует в системных сетевых буферах, вместо блокировки до тех пор, пока не будут получены все запрошенные данные - Подробности здесь. Итак, нужно использовать Read в цикле, чтобы получить все запрошенные данные.

  3. Известно, что BinaryReader генерирует исключение, когда получает меньше данных из NetworkStream, чем ожидалось, вместо того, чтобы использовать цикл для извлечения остальных (и ДА, я уверен, это означает ошибку!) - Подробности здесь

Итак, мое решение состояло в том, чтобы частично переопределить BinaryReader (я назвал свой класс BinReader), добавив некоторые полезные функции и создав правильный метод Read с циклом:

public int Read( byte[] buf, int off, int count ) {
    int read = 0;
    while( read < count ) {
        int toread = count - read;
        int portion = BaseStream.Read( buf, off, toread );
        read += portion;
        off += portion;
    }
    return read;
}

Это решило это для меня.

person mas.morozov    schedule 30.08.2013

Я не уверен, что это правильный способ исправить это, но мне показалось, что изменение reader.ReadChar() на Convert.ToChar(reader.ReadByte()) сработало.

person Homer    schedule 16.03.2021