Java String转换为十六进制

时间:2010-01-21 08:45:23

标签: java string

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

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

 {
 ...
}

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

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

我的程序执行的十六进制转换在其他十六进制值应该在的许多地方都有'fffd'。但是转换对于输入字符串的大约60%是正确的

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

4 个答案:

答案 0 :(得分:5)

我认为你不应该使用读者。读者用于阅读字符,您似乎正在处理二进制数据。直接使用InputStream并在收到字节时对其进行转换。 java中的字符是Unicode字符,我猜这是你问题的根源。

答案 1 :(得分:2)

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

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

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

答案 2 :(得分: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也产生1对1的字符; 8859-9有几个不同的字符,但1252有几个0xFFFD。

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

答案 3 :(得分:0)

出于开发目的,请查看Eclipse中已经与那些带有服务器连接器的Web容器一起使用的那个。