Получение строки utf-8 с помощью 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;

inFromDevice и InputStream получены из принятого ServerSocket.

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

Пример из лога Actual chars read: 1020 char array length: 1391

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

Если вы специально хотите UTF-8, почему вы не сказали об этом InputStreamReader?

Andreas 09.04.2019 21:52

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

Andreas 09.04.2019 21:54

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

alibttb 09.04.2019 23:53
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
2
3
80
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

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

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

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

alibttb 09.04.2019 23:56

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

erickson 10.04.2019 04:48

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

alibttb 11.04.2019 20:13

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

erickson 11.04.2019 20:15

Другие вопросы по теме