2011-03-08 23 views
0

我遇到以下程序并显示意外的结果。Java问题:从字节序列创建字符串

public class StringFromByte 
{ 
     public static void main(String[] args) 
     { 
      byte bytes[] = new byte[256]; 

      for(int i = 0; i < 256; i++) 
       bytes[i] = (byte)i; 

      String str = new String(bytes); 
      for(int i = 0, n = str.length(); i < n; i++) 
       System.out.print((int)str.charAt(i) + " "); 
     } 
} 

从技术上讲,这个程序应该按顺序打印从0到255的整数。但是如果你运行程序有时会显示这个序列(0到255),有时它会显示一些其他序列。它的行为没有指定。这是怎么回事?

+1

我无法解释非确定性行为,但我确实看到一个问题。如果将int值超过127转换为一个字节,那么它实际上是一个负值,当返回到一个int时保持负值,因此即使这是确定性的,也不会返回0 - > 255打印出来。这甚至不涉及将随机字节投入字符串时发出的编码。 – rfeak

回答

2

您正在使用的字符串构造函数使用默认的字符编码。它可以将一些字节解释为多字节字符。

试试这个:

  String str = new String(bytes, CharSet.forName("ISO-8859-1")); 

CharSet API documentation见,其中列出了标准charset名称。

声明:我通常使用这个构造函数为UTF-8。

+0

但是编码在运行时如何改变?正如Umesh提到的,“有时”顺序会改变。跨运行的编码效果不应该保持相同吗? – peakit

+0

@peakit,目前尚不清楚是否所有运行在相同平台上的相同选项。 –

0

那么,对于初学者来说,类型可以容纳的最大值是127(字节数据类型是一个8位有符号二进制补码整数)。

+0

因此,如果您将这些字节的int整数替换为-127和127之间的整数,您是否会得到预期的结果? –

1

其行为不是未指定的。

字符与字节不是一回事,但写这个的人不知道。 unicode中有大约600万个字符,但只有256个唯一字节。这意味着许多unicode字符都由多个字节表示。

您示例中的一些字节表示该字符需要多个字节,但我猜测数组中的“下一个”字节不符合有效的UTF-8字符。

要正确编码来自不是UTF-8,use this constructor的一组字节的字符串。 您将必须提供正确的字符集,以便Java可以了解字节如何适合字符。

你得到不同结果的原因是因为环境。每个环境都有一个默认的Locale来指定它的首选字符集。您使用的构造函数总是采用UTF-8字符集,因此有时会将源字节误译为乱码。

0

byte替换为char并且其按预期工作。这是因为字节的最大值为127.