Я получаю данные от UDP использование порта C ++ программирование. Предположим, мы получаем данные сокета char buf[2000]
, Когда я печатаю данные (преобразованные в шестнадцатеричный код), в сообщениях появляются неожиданные данные. Например, запустив код:
for (int i =0 ; i < 2000; i++)
{
printf(" ");
printf("%02x", buf[i]);
}
выход:
EF BF BD 01 00 1C 1E 39 5A 18 40 EF BF BD 00 38 51 EF BF BD 00 00 EF BF BD EF BF BD 00 48 00 EF BF BD 00 00 00 64 EF BF BD 1F
EF BF BD
шаблон в коде неожиданный и лишний.
Для решения этой проблемы я конвертирую char
в unsigned char
и используя код:
for (int i =0 ; i < 2000; i++)
{
printf(" ");
printf("%02x", (unsighed char)buf[i]);
}
Теперь вывод содержит желаемый результат:
aa 01 00 1c 1e 39 5a 18 50 fc 00 61 47 ae 00 00 ff b6 00 4e 01 f4 00 00 00 64 b5 4f
(Обратите внимание, что выходы для разных сообщений)
После этого я пишу сообщения Кафке. Проблема в том, что когда я читаю сообщения от Кафки, на этот раз с использованием программирования Java используя следующие коды:
ConsumerRecords<String, String> records = kafkaConsumer.poll(100);
for (ConsumerRecord<String, String> record : records) {
byte[] temp = record.value().getBytes();
StringBuffer result = new StringBuffer();
for (byte b : temp) {
result.append(String.format("%02X ", b));
result.append(" "); // delimiter
}
System.out.println(result);
и вывод:
EF BF BD 01 00 1C 1E 39 5A 18 40 EF BF BD 00 38 51 EF BF BD 00 00 EF BF BD EF BF BD 00 48 00 EF BF BD 00 00 00 64 EF BF BD 1F
снова с дополнительным EF BF BD
нежелательный образец.
Итак главный вопрос как я могу изменить код Java печатать сообщения правильным способом, точно так же, как я делал в C ++.
Вы, кажется, читаете байты, которые используют однобайтовую кодировку для представления текста (например, ISO-8859-1 или windows-1252), но вы решаете читать их, используя библиотечные функции, которые предполагают, что эти байты представляют собой представление UTF-8 текст.
«Aa» не является допустимым начальным байтом для представления символа в UTF-8. Какой бы механизм вы не использовали для преобразования байтов в символы, это знает и вставляет �
, Символ замены Юникода, как указание неверного ввода.
UTF-8 представление �
это три байта ‘ef bf bd’.
Всегда указывайте правильную кодировку при преобразовании между байтами и символами. Это не проблема в коде, который вы показали в своем вопросе; скорее это проблема с кодом, который читает байты и конвертирует их в значение String, которое record.value()
, Это тот код, который интерпретировал байт ‘aa’ как искаженную последовательность UTF-8 и поместил �
в вашей строке, чтобы указать на проблему.
Этот код, если он на Java, вероятно, используется new String(bytes)
, Следовало бы использовать new String(bytes, StandardCharsets.ISO_8859_1)
(или возможно new String(bytes, "windows-1252")
или какой-то другой однобайтовой кодировки).
Когда вы преобразуете строку обратно в байты, применяются те же правила. Если вы хотите ª
Чтобы символ был декодирован в один байт «aa», необходимо использовать однобайтовую кодировку:
record.value().getBytes(StandardCharsets.ISO_8859_1)
Как я уже сказал, в настоящее время record.value () не начинается с ª
начинается с �
, record.value (). getBytes () использует кодировку вашей системы по умолчанию (UTF-8), поэтому первые три байта возвращаемого массива являются представлением UTF-8 �
, который «EF BF BD».
Других решений пока нет …