Я пытаюсь получить строку с устройства, используя этот код:
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, которые могут вызвать это?
Бьюсь об заклад, msgLength
находится в байты, так почему вы ожидаете, что счетчик уголь будет таким же, как счетчик байт, если сообщение содержит символы, отличные от ASCII, и кодировка UTF-8. Вы знаете, как работает UTF-8, верно?
@ Андреас Андреас нет, протокол указывает, что первые 4 байта - это количество отправляемых символов UTF-8. Я не сообщил InputStreamReader о UTF-8, потому что это значение по умолчанию.
InputStreamReader
будет блокироваться только до тех пор, пока не сможет прочитать один символ в буфер или не обнаружит EOF. Нет гарантии, что буфер будет заполнен.
Если ваш протокол указывает длину отправляемой строки, получатель должен зациклиться, отслеживая количество оставшихся символов, пока все не будут прочитаны.
Это кажется логичным, я попробую, вы предлагаете чистый способ зацикливания или мне следует использовать какой-то другой ридер? @erickson
@alibttb Вы можете сделать что-то вроде CharBuffer expected = CharBuffer.wrap(cb); while (cb.hasRemaining()) r.read(expected);
Вы должны сделать что-то подобное при чтении данных для ByteBuffer
, которое содержит длину сообщения.
ты имеешь в виду CharBuffer expected = CharBuffer.wrap(cb); while (expected.hasRemaining()) { r.read(expected); }
@erickson
@alibttb Да, извините за опечатку. У вас это правильно.
Если вы специально хотите UTF-8, почему вы не сказали об этом
InputStreamReader
?