2017-03-01 19 views
0

我有以下代码,它打印出来自字符串s0s1的字节;输出结果评论:Java获取字符的十进制字节表示形式

public static void main(String[] args) throws UnsupportedEncodingException { 
    String s0="H\u00ebllo"; 
    String s1="Hëllo"; 

    byte[] bytes=s0.getBytes("ISO8859_1"); //72 -21 108 108 111 
    //byte[] bytes=s1.getBytes("ISO8859_1"); //72 -61 -85 108 108 111 
    //byte[] bytes=s0.getBytes("UTF-8"); //72 -61 -85 108 108 111 
    //byte[] bytes=s1.getBytes("UTF-8"); //72 -61 -125 -62 -85 108 108 111 
    for (int i=0, i<bytes.length; i++) { 
     System.out.println(bytes[i]); 
    } 
} 

我不明白的是这些数字来自哪里。如果所有字符代码都应该是正数,为什么会有负数?为什么在第二种情况下有6个数字?为什么ë字符的数字在使用Unicode符号和字面值时有所不同?

编辑

我了解,这些数字来自第一被转换为无符号数:

ë(ISO8859_1) = 0xeb = 235 = 11101011 = -21 (two's complement for signed numbers)

ë (UTF-8) = 0xc3 0xab => 0xc3 = 195 = 11000011 = -61, 0xab = 171 = 10101011 = -85

但我还是不明白的是s0s1字符串之间的差异。在这两种情况下,我要求从getBytes()ISO8859_1字节,而在第二种情况下,我仍然得到UTF-8的字节。

编辑:

而且byte[] bytes=s1.getBytes("UTF-8");结果输出:

72 -61 -125 -62 -85 108 108 111

我真的很困惑。

编辑

System.out.println(System.getProperty("file.encoding")); 
System.out.println(java.nio.charset.Charset.defaultCharset()); 

两个给UTF-8。源文件在UTF-8

+0

'k'的用途是什么? – Andreas

+0

@Andreas,它是大型项目的一部分,因个人原因需要'k'。无论如何编辑帖子。 – parsecer

+1

再一次,您的源文件以UTF-8格式存储,所以'ë'存储为两个字节。你的编译器采用了不同的编码方式,并将UTF-8'''曲解为'?',所以当代码执行时,它不知道有关'Hëllo'的任何信息,而只知道'Hëllo'。 –

回答

2

在Java中,byte原始类型是signed,这意味着范围从-128到+127(第一位被认为是数字的符号)。

在扩展ASCII和其他8位编码(如ISO-8859-1)中,存在字节值大于127的字符。这些字符在作为标准Java byte打印时显示为负数。

如果您使用的是UTF-8(或另一种Unicode UTF编码),则非ASCII字符由2-4个字节表示,并且它们中的每一个都可能“大于127”,因此它们将显示作为负面的,当你只是将它们打印为byte的值。

+0

您能否介绍一下Java如何在0xeb = 235(011101011)中生成-21(111101011)?这里使用的规则是什么?对于大于127的所有数字,通过1-第一个零位使其中的负数出现? – parsecer

+2

@parsecer你在找什么是[Two's complement](https://en.wikipedia.org/wiki/Two's_complement)的描述,这是大多数计算机存储带符号整数的方式。 – Andreas

+0

@parsecer当您的源文件编码与编译器期望的编码不同时,迟早会遇到严重的麻烦。这个答案的最后一段是不正确的,Java中的String与UTF-8没有关系,'String.getBytes(“ISO8859_1”)'永远不会给你一个字符的两个字节。 –

3

字节是Java中的带符号数字,范围为-128到127.第二种情况下有6个数字,因为您的源文件使用UTF-8编码,Java编译器假定可能不是特定于平台的编码UTF-8。使用IDE查找与源和/或编译器编码相对应的设置时。使用javac进行编译时,请尝试指定-encoding UTF-8

+0

但是''''是ISO的'U + 00EB',在'ISO8859_1'中是'0xeb'。 0xeb应该是十进制的235。 – parsecer

+1

在使用UTF-8时,将源代码中的字符串作为字符串文本的一部分存储为两个字节。并且,在Java *中,不存在任何应该是十进制235的* byte *值。 –

0

在java中,所有数字类型都是signed(与unsigned相对)。请注意,char不是数字类型,即使它可以算术使用(滥用)。

您的编码给出-21,这只是Java的byte表示0b111010110xEB

+0

235怎么会变成-21?毕竟,第一位是零,这意味着它是一个正数。完成了转换235-> 011101011并在此处反转http://www.exploringbinary.com/twos-complement-converter/,-21从未出现过...... – parsecer

+0

这是因为您指定了9位,因为该站点向您显示错误,因为235超出范围。 –

+0

我编辑了这个问题,请解释's0'和's1'的区别? – parsecer

相关问题