获取字符的Unicode值

80

在Java中是否有办法获取任何字符的Unicode等效值?例如:

假设有一个方法getUnicode(char c)。调用getUnicode('÷')应该返回\u00f7


1
在Java中,字符已经是Unicode。 - user502187
6个回答

75

你可以使用这个一行代码来处理任何Java字符:

System.out.println( "\\u" + Integer.toHexString('÷' | 0x10000).substring(1) );

但它只能处理Unicode字符直到Unicode 3.0,这就是为什么我强调你可以用任何Java字符来完成它。

由于Java在Unicode 3.1出现之前就被设计了,所以Java的char原始类型不足以表示Unicode 3.1及以上版本:不再有“一个Unicode字符对应一个Java char”的映射(而是使用了一个巨大的hack)。

因此,在这里您确实需要检查您的要求:您是否需要支持Java char或任何可能的Unicode字符?


谢谢。我已经用这种方式检查了所有字符,目前看起来都很好。 - Saurabh
4
“怪异的黑客”是指广泛使用的UTF-16编码。虽然不是完美的选择,但它被广泛理解,并且比仅支持UCS-2编码要好得多。 - Joachim Sauer
1
@Joachim:然而,现在String.charAt返回“半个字符”,而String.length返回的内容可能与字符数不同,这不是很丑陋吗?(这里的“字符”指Unicode代码点,而不是Java字符)String类应该是独立于编码问题的(在Unicode 3.1之前也确实如此)。 - Thilo
1
@Joachim:我所指的正是Thilo描述的内容。对我来说,真正的问题在于为了保持向后兼容性,我们有一个方法charAt(...),它并不返回一个字符。这很糟糕。方法名称保持不变,但它的Javadoc已经被重新编写了。现在我们有了codePointAt(...),几乎没有人知道,而且问题非常令人困惑。这不完全是Java设计者的错,因为正如我在答案中所写的那样,Java是在Unicode 3.1发布之前设计的。只是有点遗憾char是16位而不是32位。 - SyntaxT3rr0r
是的,我知道这个问题,并且它确实是一个问题。我不否认这一点。但至少我们有一个被广泛理解的“修复”(或者说是变通方法),而不是陷入整个“哦不!许多人无法使用ASCII编写他们的语言”的编码地狱中。UTF-16并不完美,但它是标准化和被广泛理解的。 - Joachim Sauer

41

如果您使用Java 5,请使用char c = ...; String s = String.format ("\\u%04x", (int)c);

如果您的源不是Unicode字符(char)而是字符串,则必须使用charAt(index)获取位置index处的Unicode字符。

不要使用codePointAt(index),因为它将返回24位值(完整的Unicode),这些值无法仅用4个十六进制数字(需要6个)表示。请参见文档以获得说明

[编辑]为了清楚起见:此答案不是使用Unicode,而是Java用于表示Unicode字符的方法(即代理对),因为char是16位,而Unicode是24位。问题应该是:“如何将char转换为4位十六进制数”,因为它并不(真正地)与Unicode有关。


2
@Aaron Digulla:认为charAt(...)返回Unicode字符是一个常见的错误。它并不是这样的。只有当您的字符串由Unicode 3.0 / BMP字符组成时,charAt(...)才会返回Unicode字符。我不同意他不应该使用codePointAt。他应该使用codePointAt和一种能够编码BMP之外字符的方法。 - SyntaxT3rr0r
codePointAt可能更好,但是假设你真的需要它,那么找到正确的索引值会变得棘手。 - Thilo
@Aaron Digulla:问题在于,在调用codePointAt(...)时没有索引魔法。codePointAt(...)始终返回Unicode字符,即使它超出BMP。当调用charAt(...)时可能会遇到问题,因为如果在一个超出BMP的Unicode字符后调用charAt(...),就无法保证你将读取到一个字符。但也许我误解了你的意思?如果我没记错的话,有些例子中包含了音符(这些是超出BMP的字符)的字符串。但也许我误解了你的问题? - SyntaxT3rr0r
@WizardOfOdds:我猜这位提问的人会一直将一个完整的字符串转换,所以charAt()是安全的。但我明白你的意思:你可以循环遍历0到s.codePointCount(0,s.length()),并且为迭代器的每个值调用s.codePointAt()。 - Aaron Digulla
嗨,我是Saurabh(Ranu),请提供Hibernate全文搜索的详细信息和配置。 - saurabh
显示剩余2条评论

14
private static String toUnicode(char ch) {
    return String.format("\\u%04x", (int) ch);
}

8
复制了三年前的现有答案。 - james.garriss
4
虽然最佳答案含糊不清,但这个答案给出了更清晰的解释。我的意思是,这个 ( "\\u" + Integer.toHexString('÷' | 0x10000).substring(1) ) 到底是什么鬼? - Все Едно
"\u" + String.format("%04x", (int) c).toUpperCase() 的翻译内容为: - fl0w

10
char c = 'a';
String a = Integer.toHexString(c); // gives you---> a = "61"

1

我在网上找到了这段不错的代码。

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Unicode {

public static void main(String[] args) {
System.out.println("Use CTRL+C to quite to program.");

// Create the reader for reading in the text typed in the console. 
InputStreamReader inputStreamReader = new InputStreamReader(System.in);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);

try {
  String line = null;
  while ((line = bufferedReader.readLine()).length() > 0) {
    for (int index = 0; index < line.length(); index++) {

      // Convert the integer to a hexadecimal code.
      String hexCode = Integer.toHexString(line.codePointAt(index)).toUpperCase();


      // but the it must be a four number value.
      String hexCodeWithAllLeadingZeros = "0000" + hexCode;
      String hexCodeWithLeadingZeros = hexCodeWithAllLeadingZeros.substring(hexCodeWithAllLeadingZeros.length()-4);

      System.out.println("\\u" + hexCodeWithLeadingZeros);
    }

  }
} catch (IOException ioException) {
       ioException.printStackTrace();
  }
 }
}

原始文章


谢谢。你给了我我所要求的东西。然而,当我尝试一些俄语字符时,它返回相同的Unicode值。我认为不同的字符应该有不同的Unicode值。我尝试了以下字符 -л, и, ц, т, я 返回 \u003F。 - Saurabh
1
我非常确定,对于超过0xFFFF的代码点,那段代码是不正确的。 - SyntaxT3rr0r
1
俄语字符应该在基本多语言平面上,即(0xFFFF以下)。 - Thilo
@Thilo:哦,我知道,我并不是在评论Saurabh的俄语示例。在发表评论之前,我使用了他的字符来尝试我的方法,它们可以正常工作。我只是想说,我相当确定那里的方法不能处理BMP之外的字符。 - SyntaxT3rr0r
2
惊人的是,为了解决一个简单的问题,某些人必须编写大量的代码。Aaron的解决方案只有40个字符长,而这里有1124个字符。 - jarnbjo

1

你是否对使用Unicode很挑剔?因为如果你编写程序使用“dec”值或(HTML-Code),那么你可以在char和int之间简单地进行数据类型转换,这在Java中更加简单。

char a = 98;
char b = 'b';
char c = (char) (b+0002);

System.out.println(a);
System.out.println((int)b);
System.out.println((int)c);
System.out.println(c);

输出以下内容

b
98
100
d

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接