首页 > 解决方案 > Java Scanner.nextLine() 错误地将 unicode (emoji) 解析为新行

问题描述

最简单的例子演示:

    String test = "salut ð\u009F\u0098\u0085 test";
    Scanner scan = new Scanner(test);
    System.out.println("1:" + scan.nextLine());
    System.out.println("2:" + scan.nextLine());

这是用户输入中的一个字符串,所以不幸的是我不能 100% 确定那个 unicode 是什么,但如果我没记错的话,它是一个表情符号(我在发送消息时看到了该消息)。

输出是:

    1:salut ð
    2: test

我的预期输出只有 1 行(即示例代码应该给出一个NoSuchElementException,因为第二个nextLine()应该失败。)。为什么解析为两行?什么是潜在的解决方法?

当我在文本编辑器中打开文件时,它不会正确地将该 unicode 视为新行。

标签: javajava.util.scanner

解决方案


为什么解析为两行?

虽然这是一个不常见的代码点,但 U+0085 的 unicode 名称NEXT LINE [NEL],我猜它可以被认为是一个换行符。

但是有没有一个原因BufferedReader,像 Sublime Text 这样的文本编辑器不会将其解析为实际的新行,而Scanner呢?

如果您查看 和 的相应Scanner文档BufferedReader

Scanner.nextLine

将此扫描器前进到当前行并返回被跳过的输入。此方法返回当前行的其余部分,不包括末尾的任何行分隔符。位置设置为下一行的开头。

由于此方法继续搜索输入寻找行分隔符...

BufferedReader.readLine

读取一行文本。一行被认为是由换行符 ('\n')、回车符 ('\r') 或紧跟换行符的回车符中的任何一个终止的。

Scanner.nextLine只是说“行分隔符”是一个非常模糊的术语(它当然不是指只有一个代码点的 Unicode 类别“行分隔符”),而BufferedReader.readLine文档准确地说明了行是什么。

考虑到如何Scanner处理本地化的数字格式和东西,我的猜测是它被设计为比BufferedReader.

查看我的 JDK 版本的源代码,Scanner考虑以下字符串“行分隔符”:

  • \r\n
  • \n
  • \r
  • \u2028
  • \u2029
  • \u0085

之所以\u0085被认为是换行符,显然与 XML 解析有关。


推荐阅读