我想将十进制转换为ascii,这是代码返回意外结果。这是我正在使用的代码。
public static void main(String[] args) {
char ret= (char)146;
System.out.println(ret);// returns nothing.
我希望能够获得单曲"'"根据{{3}} 有谁遇到过这个?感谢。
答案 0 :(得分:6)
所以,有几件事。
首先,您链接到的页面会说明有关代码点范围:
扩展的ASCII码(字符代码128-255)
8位ASCII表有几种不同的变体。下表符合ISO 8859-1,也称为ISO Latin-1。代码128-159包含Microsoft®WindowsLatin-1扩展字符。
这是错误的,或者至少对我来说是误导性的措辞。 ISO 8859-1 / Latin-1 does not define code point 146(和another reference just because)。所以这已经在惹麻烦了。如果您通过String
进行转换,也可以看到此信息:
String s = new String(new byte[] {(byte)146}, "iso-8859-1");
System.out.println(s);
输出相同的“意外”结果。它出现它们实际指的是Windows-1252集(又名“Windows Latin-1”,但这个名称现在几乎完全过时了),它定义了代码点作为正确的单引号(对于在146处提供此字符的其他字符集,请参阅this list并查找在0x92处提供该字符的编码),我们可以对此进行验证:
String s = new String(new byte[] {(byte)146}, "windows-1252");
System.out.println(s);
所以第一个错误是页面令人困惑。
但是最大的错误是你不能按照自己的方式去做你想做的事情。 Java中的char
是一个UTF-16代码点(或者一半,如果你代表补充字符> 0xFFFF,单个char
对应一个BMP点,一对或者int
对应于整个范围,包括补充范围。)
不幸的是,Java并没有为单字符转换公开大量的API。即使Character
也没有任何现成的方法可以将您选择的字符集转换为UTF-16。
因此,一个选项是通过String
进行,如上面的示例所示,例如:将您的代码点表示为原始byte[]
数组并从那里转换:
String s = new String(new byte[] {(byte)146}, "windows-1252");
System.out.println(s);
char c = s.charAt(0);
System.out.println(c);
您可以通过char
再次抓取s.charAt(0)
。请注意,执行此操作时必须注意字符集。在这里我们知道我们的字节序列对指定的编码有效,并且我们知道结果只有一个char
长,所以我们可以这样做。
但是,你必须注意一般情况下的事情。例如,您的字节序列和字符集可能会产生UTF-16补充字符范围内的结果。在这种情况下,s.charAt(0)
是不够的,而s.codePointAt(0)
中需要存储int
。
作为替代方案,同样的警告,您可以使用Charset
进行解码,尽管它很笨重,例如:
Charset cs = Charset.forName("windows-1252");
CharBuffer cb = cs.decode(ByteBuffer.wrap(new byte[] {(byte)146}));
char c = cb.get(0);
System.out.println(c);
请注意,我并不完全确定Charset#decode
如何处理补充字符并且现在无法真正测试(但任何人都可以随意加入)。
顺便说一下:在你的情况下,146(0x92)直接转换为char
对应于UTF-16字符“PRIVATE USE TWO”(see also),并且所有的赌注都是关闭的你最终会在那里展示。此字符为classified by Unicode as a control character,似乎属于为ANSI终端控制保留的字符范围(尽管实际上并未使用AFAIK,但无论如何都在该范围内)。如果某些语言环境中的浏览器可能将其作为兼容性的右单引号,我也不会感到惊讶,但是终端对它做了一些奇怪的事情。
另外,fyi是right single quote is 0x2019的官方UTF-16代码点。您可以使用该值可靠地将其存储在char
中,例如:
System.out.println((char)0x2019);
您还可以通过查看从Windows-1252转换后的值来自行查看:
String s = new String(new byte[] {(byte)146}, "windows-1252");
char c = s.charAt(0);
System.out.printf("0x%x\n", (int)c); // outputs 0x2019
或者,为了完整性:
String s = new String(new byte[] {(byte)146}, "windows-1252");
int cp = s.codePointAt(0);
System.out.printf("0x%x\n", cp); // outputs 0x2019
答案 1 :(得分:0)
您提到的页面提到值160到255对应于ISO-8859-1(又名拉丁语1)表;对于128到159范围内的值,它们来自拉丁语1的Windows特定变体(ISO-8859-1保留未定义的范围,由操作系统分配)。
Java字符基于UTF16,它本身基于Unicode表。如果您想特别引用正确的引号字符,可以在Java中将其指定为'\u2019'
(参见http://www.fileformat.info/info/unicode/char/2019/index.htm)。