2017-03-01 21 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

相關問題