Получение строки utf-8 с помощью InputStreamReader из сокета?

#java #sockets #inputstream #inputstreamreader

#java #сокеты #входной поток #inputstreamreader

Вопрос:

Я пытаюсь получить строку с устройства, используя этот код:

         byte[] buf = new byte[4];
        int read = inFromDevice.read(buf);
        Logger.getLogger(Utill.class.getName()   " DEBUG_ERR01").log(Level.INFO, "Bytes read: {0}", read);
        int msgLength = ByteBuffer.wrap(buf).getInt();
        Logger.getLogger(Utill.class.getName()   " DEBUG_ERR01").log(Level.INFO, "Message length: {0}", msgLength);
        Reader r = new InputStreamReader(inFromDevice);
        char[] cb = new char[msgLength];
        int actualCharsRead = r.read(cb);
        Logger.getLogger(Utill.class.getName()   " DEBUG_ERR01").log(Level.INFO, "Actual chars read: {0} char array length: {1}", new Object[]{actualCharsRead, cb.length});
        String msgText = String.valueOf(cb, 0, cb.length);
        Logger.getLogger(Utill.class.getName()   "Messages Loggining recieve: ").log(Level.INFO, msgText);
        return msgText;
  

информационное устройство — это InputStream, полученный из принятого ServerSocket.

Код работает и возвращает сообщения большую часть времени, но иногда я получаю сообщения меньше msgLength (что неверно в соответствии с протоколом)

Примером из журнала является Actual chars read: 1020 char array length: 1391

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

Комментарии:

1. Если вам конкретно нужен UTF-8, почему вы не сказали InputStreamReader об этом?

2. Бьюсь об заклад, msgLength это в байтах , так почему вы ожидаете, что количество символов будет таким же, как количество байт , если сообщение содержит символы, отличные от ASCII, а кодировка — UTF-8. Вы ведь знаете, как работает UTF-8, верно?

3. @Andreas нет, протокол определяет, что первые 4 байта — это количество отправляемых символов UTF-8. Я не сообщил InputStreamReader о UTF-8, потому что это значение по умолчанию.

Ответ №1:

InputStreamReader Будет блокироваться только до тех пор, пока не сможет прочитать один символ в буфер или обнаружить EOF. Нет гарантии, что буфер будет заполнен.

Если ваш протокол указывает длину отправляемой строки, получателю необходимо выполнить цикл, отслеживая количество оставшихся символов, пока все они не будут прочитаны.

Комментарии:

1. Это кажется логичным, я попробую, вы предлагаете чистый способ выполнения цикла или мне следует использовать какой-то другой вид чтения? @erickson

2. @alibttb Вы могли бы сделать что-то вроде CharBuffer expected = CharBuffer.wrap(cb); while (cb.hasRemaining()) r.read(expected); Вы должны делать что-то подобное при чтении данных для ByteBuffer , которые содержат длину сообщения.

3. вы имеете в виду CharBuffer expected = CharBuffer.wrap(cb); while (expected.hasRemaining()) { r.read(expected); } @erickson

4. @alibttb Да, извините за опечатку. У вас все правильно.