从套接字到字节数组的读取数据中的意外字符

Unexpected characters in reading data from socket to byte array

本文关键字:意外 字符 数据 读取 到字节 数组 套接字      更新时间:2023-10-16

我使用 port使用 c 编程从 udp 获取数据。假设我们接收到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

(请注意,输出适用于不同的消息)

之后,我将消息写给Kafka。问题是当我使用以下代码使用Java编程读取Kafka的消息时,

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表示形式的有效启动字节。无论您使用哪种机制将字节转换为字符,都知道这一点,并插入 ,unicode替换字符,作为无效输入的指示。

的UTF-8表示是三个字节" EF BF BD"。

在字节和字符之间转换时,始终指定正确的字符集。这不是您在问题中显示的代码中的问题;相反,这是读取字节并将其转换为 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()使用系统的默认charset(UTF-8),因此返回数组的前三个字节是的UTF-8表示,即'EF BF BD'。