字符串在Java中使用toString后,为什么十六进制表示不能正确打印为‰?
在执行XOR并从十六进制转换为字符串后,我希望十六进制值“89”显示为“‰”,但Eclipse显示的是“?”。调试时,字符实际上为空。为什么?
- 我将字符串“r”转换为hex=>;"72". 李>
- 然后我将“72”与“FB”(ā)=>;"89". 李>
然后,我使用以下函数将“89”转换为字符串:
public static String HexToString(String hex){ StringBuilder sb = new StringBuilder(); StringBuilder temp = new StringBuilder(); for( int i=0; i<hex.length()-1; i+=2 ){ //grab the hex in pairs String output = hex.substring(i, (i + 2)); //convert hex to decimal int decimal = Integer.parseInt(output, 16); //convert the decimal to character sb.append((char)decimal); temp.append(decimal); } System.out.println("Decimal : " + temp.toString()); return sb.toString(); }
将结果打印到控制台后,我看到“?”而不是“/”。怎么了
编辑: 下面是显示decimal值和(char)decimal调试值的屏幕截图。
# 1 楼答案
首先,Java在内部是完全Unicode的(虽然不是Unicode的最新版本,但复杂的原因在这里并不重要)。89十六进制将是
\u0089
,这是一个扩展控制字符(带对齐的字符列表),就像它在字符集ISO-8859-1中一样;对于前256个字符,Unicode与ISO-8859-1完全相同。根据你的描述,我猜你是在Windows上,并且配置了使用CP1252 character set的东西,它将89个十六进制解释为‰
,但是Unicode的转换是通过映射到等效字符来完成的(在打印到控制台的过程中),而不仅仅是清除字节;由于该C1控制字符在CP1252中没有等效字符,因此它最终将作为替换字符(本例中为问号)这个故事的寓意是字符是而不是字节,在这个领域工作时需要非常小心使用字符集。(或者你应该使用一个完全Unicode的系统,在这个系统中,这些问题基本上消失了,尽管这样做的代价是字符成为比以前复杂得多的实体。)