2010-01-21 21 views
1

我正在处理一个tcp/ip套接字侦听器,该侦听器在端口80上侦听从远程主机到达的数据。现在这些传入的数据是不可读的格式,所以我保存了这些传入数据,因为它们最初是在一个字符串中,然后将该字符串转换为字符数组,然后对于数组中的每个索引,我已将内容转换为十六进制。现在的问题是,数据转换为十六进制好吧,但在某些地方转换不正确,结果十六进制是'fffd'。在产生的十六进制应该是'bc'(0xBC)的地方,它是'fffd'(0xFF 0xFD)。我不得不相信传入数据的某些部分没有被我的java程序正确读取。 我使用BufferefInputStream和InputStreamReader来读取传入数据,并以下面的方式检查流结束。Java字符串转换为十六进制

BufferedInputStream is = new BufferedInputStream(connection.getInputStream()); 
    InputStreamReader isr = new InputStreamReader(is); 
    while(isr.read()!=-1) 

{ 
... 
} 

其中'连接'是套接字对象。

即时通讯套接字的输入数据是#SR,IN-0002005,10:49:37,16/01/2010,$ < 49X™™š@(bN>™™šBB©:4äý 01300>ÀäCåKöA÷d>。

十六进制转换我的程序确实在许多地方,其他的十六进制值应该是已经‘FFFD’,转换,虽然是60%左右的输入字符串的正确

任何关于为什么我得到的十六进制转换不是它应该是什么指针会有很大帮助。

+0

听起来像一个编码问题。您是否考虑了编码中的传入数据的格式? – Aadith 2010-01-21 08:49:17

+0

林相当肯定,这不是一个编码问题,因为我被告知,在VB中完成相同的事情,产生不同的和正确的结果。 – ping 2010-01-21 08:52:13

回答

5

我不认为你应该使用一个阅读器。阅读字符,你似乎正在处理二进制数据。直接使用InputStream并在收到它们时转换字节。在java中的字符是Unicode字符,我猜是你的问题的来源。

+0

如果它不是问题,你能帮我解释一下这个案子的小片段吗? – ping 2010-01-21 09:17:19

+0

@ping从您的问题的代码中,只需删除创建InputStreamReader的行,并通过引用InputStream替换该Reader的所有引用,例如, 'while(isr.read()!= - 1)'变成'while(is.read()!= - 1)'。尽管您可能需要将读取的返回值存储在某处,因为那是读取的字节,例如while((nextByte = is.read())!= - 1)' – 2010-01-21 09:44:42

2

Java字符串在处理透明二进制数据时不像处理VB(或大多数其他语言)那样容易“滥用”。 VB将字符串内部视为字节数组,而在Java中,字符串是有序的字符列表。

在你的情况下,你用InputStreamReader包装你的InputStream,当你将InputStream传递的字节转换为InputStreamReader传递的字符时,会导致你的平台的默认字符编码被使用。一些主要使用的ISO 8859-X字符集不使用范围为0x00至0x1f和0x7f至0xbf的字节,因此如果您正在使用这种编码并从这些范围读取一个字节,则InputStreamReader将返回“替换字符“用代码点0xfffd表示一个未知的字符。

唯一“正确的”方法是省去InputStreamReader并使用字节数组作为二进制数据。

1

当转换字节字符与InputStreamReader,编码使一个巨大的差别:

public static void main(String[] args) throws Exception { 
    checkEncoding("ISO-8859-1"); 
    checkEncoding("ISO-8859-9"); 
    checkEncoding("Windows-1252"); 
    checkEncoding("UTF-8"); 
    checkEncoding("UTF-16BE"); 
    checkEncoding("Big5"); 
    checkEncoding("Shift-JIS"); 
    } 

    private static void checkEncoding(String encoding) throws IOException { 
    byte[] all = new byte[256]; 
    for (int i = 0; i < all.length; ++i) all[i] = (byte) i; 
    ByteArrayInputStream bais = new ByteArrayInputStream(all); 
    InputStreamReader isr = new InputStreamReader(bais, encoding); 
    char[] ca = new char[256]; 
    int read = isr.read(ca); 
    System.out.println(encoding + ":" + read); 
    for (int i = 0; i < read; ++i) { 
     if (ca[i] != i) { 
     System.out.println(Integer.toHexString(i) + "->" + 
      Integer.toHexString(ca[i])); 
     } 
    } 
    } 

“为预期的”,其工作方式只有一个是ISO-8859-1,其被定义为所述第一Unicode中的256个字符。 ISO-8859-9和Windows-1252也产生一对一的字符; 8859-9有几个不同的字符,但1252有几个0xFFFD。

由于字节的排列方式,UTF-8的0x7F之后的所有内容都不好。当然,你得到UTF-16的一半字符,而其他多字节编码是一团糟。

0

为了开发目的,请查看Eclipse中已经用于那些带有服务器连接器的Web容器的开发目的。

相关问题