我有以下XML文件,其中包含表情符号:http://pastebin.com/8f0GeE96
现在,我想要的是将每个unicode字符转换为它的代码(作为字符串)。我已为此原因编写了以下代码。问题是我得到了很多dup(即d83d
),这让我觉得我的解析出了问题。对此有何解释?
public static void main(String[] args) {
File file = new File("c:\\EmojisList.plist.txt");
try {
BufferedReader in = new BufferedReader(
new InputStreamReader(new FileInputStream(file), "UTF8"));
String str;
while ((str = in.readLine()) != null) {
if(str.trim().startsWith("<string>"))
{
int emoji_pos = str.indexOf('>') + 1;
char emoji_char = str.charAt(emoji_pos);
String emoji_code_str = Integer.toHexString(emoji_char);
System.out.println(emoji_code_str);
}
}
in.close();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
答案 0 :(得分:1)
Unicode标准以一系列字符开始,其中16位(两个字节)就足够了。
但是,添加了越来越多的脚本和符号,而现在,您无法用16位表示所有字符。代码点的合法范围是从U + 0到U + 10FFFF。
不幸的是,这不适合Java char
,它只有16位,能够表示0到FFFF的值。
大多数常见的西方语言都没有这个问题 - 包括口音,俄语,阿拉伯语,希伯来语等在内的拉丁语范围都在16位范围内。即使是常见的中文和日文字符都在此范围内。
但是大多数表情符号实际上都在&#34;扩展&#34;范围,在unicode&#34;其他符号和象形文字&#34;和#34;表情符号&#34;块,范围从U + 1F300到U + 1F5FF,从U + 1F600到U + 1F67F。
此范围内的字符使用UTF-16编码以字符串表示,该编码基本上为每个此类字符使用两个char
值。因此,如果角色的代码点(其官方unicode值)在U + 10000到U + 10FFFF范围内,则有两个{{1}}值,其中一个来自U + D800范围通过U + DB7F(&#34;高代理&#34;),以及范围U + DC00到U + DFFF(&#34;低代理&#34;)中的一个用于表示它。
因此,当您在程序中读取char
的值时,实际上只读取实际字符的前半部分。事实上,所有的表情符号都是在表情符号&#34;范围具有U + D83D的高代理特征。
因此,要获取表情符号的实际Unicode代码点,您需要将UTF-16表示转换为实际的charAt(emoji_pos)
值。 int
是不够的。您可以使用char
和String
类中可用的方法来执行此操作。
在这种情况下,您只需使用codePointAt
方法,而不是使用Character
。
所以,而不是
charAt
使用:
char emoji_char = str.charAt(emoji_pos);
有关详细信息,请阅读Unicode Consortium网站上的UTF FAQ。
注意:Java编码约定是变量,字段方法名称应该是较低的驼峰情况:第一个单词以小写字母开头,其他单词以大写字母开头,没有下划线。因此,变量名称应为int emojiCodePoint = str.codePoint(emojiPos);
,而不是emojiCodePoint
。下划线仅在常量名称中可接受,这些名称全部为大写(例如emoji_code_point
)。