在Java中读取Unicode字符

3

我是一个Java新手,当我给一个Unicode字符串赋值时,

  String str = "\u0142o\u017Cy\u0142";
  System.out.println(str);

  final StringBuilder stringBuilder = new StringBuilder();
  InputStream inStream = new FileInputStream("C:/a.txt");
  final InputStreamReader streamReader = new InputStreamReader(inStream, "UTF-8");
  final BufferedReader bufferedReader = new BufferedReader(streamReader);
  String line = "";
  while ((line = bufferedReader.readLine()) != null) {
      System.out.println(line);
      stringBuilder.append(line);
  }

为什么在两种情况下结果不同,文件a.txt也包含相同的字符串。但是当我打印文件输出时,它打印出z\u0142o\u017Cy\u0142而不是实际的Unicode字符。有什么想法如何做到如果我想要文件内容也像字符串一样被打印。


你的文件里面是真的包含了带有斜杠和u的"\u0142o\u017Cy\u0142"吗?还是它实际上包含了UTF-8编码的文本? - unbeli
如果您在Eclipse或Windows中进行测试,很难确定它是否正常工作。首先确保您的文件被创建为UTF8文本文件,并在Swing文本字段中显示其内容;这应该会向您展示正确的字形。 - Paul Gregoire
7个回答

5

您的代码应该是正确的,但我猜测文件"a.txt"中并不包含使用UTF-8编码的Unicode字符,而是转义字符串"\u0142o\u017Cy\u0142"。

请使用支持UTF-8的编辑器(例如Windows上的最新版本Notepad或Notepad++)检查文本文件是否正确。或者使用您喜欢的十六进制编辑器进行编辑 - 它不应该包含反斜杠。

我已经尝试了将"€"作为UTF-8编码的文件内容,并且它可以被正确地打印出来。请注意,根据您终端编码(在Windows上真的很麻烦)和字体,不是所有的Unicode字符都可以被打印出来。


5

Java将源代码中的unicode转义字符(例如\u0142)解释为您实际在源代码中键入该字符(带有划线的拉丁小写字母L)。

Java不会解释从文件中读取的unicode转义字符。

如果您将String str = "\u0142o\u017Cy\u0142";写入Java程序中的文件a.txt,然后在编辑器中打开该文件,您将在文件中看到字符本身,而不是\uNNNN序列。

如果您使用原始发布的程序并读取那个a.txt文件,您应该会看到您所期望的内容。


但是,当我在资源包中指定代码并加载它们时,它们会正确显示Unicode字符。那么它是如何与属性文件一起工作的? - Rakesh
@Rakesh - 正如 BalusC 在他的回答中提到的那样,java.util.Properties 有一个 loadConvert() 方法来进行转换。我的意思是,仅仅从文件中读取并不会进行转换。 - Stephen P

2
似乎你的文件中实际上包含文本z\u0142o\u017Cy\u014,即其中有Unicode转义序列。
可能有库可以解码这些内容,但是你也可以自己完成。根据Java语言规范,转义序列始终采用\uxxxx的形式,因此你可以获取字符的4位十六进制值xxxx,使用Integer.parseInt将其转换为整数,再将其转换为字符,最后用字符替换整个\uxxxx序列。

1

所以,你想要取消转义 Unicode 代码点吗?目前没有公共 API 可用于此。java.util.Properties 类有一个 loadConvert() 方法可以做到这一点,但它是 private 的。如果你想重用它,请查看 Java 源代码。它通过简单的解析来进行转换。我不会在这里使用正则表达式,因为在特定情况下这太容易出错了。

或者你应该使用 java.util.Properties 或其 i18n 对应项 java.util.ResourceBundle,并使用 .properties 文件而不是普通的 .txt 文件。

另请参阅:


0

我在这个答案中发布了Java代码,用于反转义(“去转义”?)这些内容和其他许多内容。


0

我认为应该是“UTF8”,而不是“UTF-8”。

我在这里看到的:来源


2
UTF-8和UTF8的区别取决于您使用java.io还是java.nio。根据我的经验,无论哪种方式都不会有太大影响。 - Paul Gregoire
当我给你下投票时,我正在查看 java.nio.CharSet 的文档(用于 InputStreamReader 中的另一个构造函数),该文档将其列为 UTF-8。但是,由于你此后编辑了你的答案,我能够取消这个投票。 - Powerlord
UTF-8 是编码的显示名称;UTF8 是别名。它们是等效的。 - Richard Fearn
@R. Bemrose 好的! @Richard 明白 :) - InsertNickHere

-1

你使用了FileInputStream,它是一个字节码读取器而不是字符读取器。尝试使用FileReader代替。

例如:

BufferedReader inputStream = new BufferedReader(new FileReader("C:/a.txt"));

然后你可以使用面向行的I/O BufferedReader来读取每一行。应该避免使用FileInputREader这种低级别的I/O。除非你需要写入字节/二进制数据,否则最好使用字符流进行写入和读取。


我忘了提到,尝试以十六进制查看你的a.txt文件,看看你得到了什么,从低级别的角度来看,你会更加理解这些东西是如何工作的。 - Alex
什么?他正在使用字符流:InputStreamReader。而字符流必须建立在字节流之上,因此他使用了FileInputStream。他的做法是完全正确的。如果有什么问题,我们应该建议人们不要使用FileReader,因为它依赖于平台相关的系统属性(即默认编码)。 - Alan Moore

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