【问题标题】:Printing Unicode from Scala interpreter从 Scala 解释器打印 Unicode
【发布时间】:2009-12-22 17:49:01
【问题描述】:

使用 scala 解释器(即在命令行上运行命令“scala”)时,我无法正确打印 unicode 字符。当然 a-z、A-Z 等打印正确,但例如 € 或 ƒ 打印为 ?。

print(8364.toChar)

结果?而不是欧元。 可能我做错了什么。我的终端支持 utf-8 字符,即使我将输出通过管道传输到单独的文件并在文本编辑器中打开它,?显示出来。

这一切都发生在带有 Scala 2.8(夜间构建)和 Java 1.6.0_17 的 Mac OS X(Snow Leopard,10.6.2)上)

【问题讨论】:

  • 您在哪个操作系统中运行解释器?哪个 Scala 版本?

标签: scala utf-8 interpreter


【解决方案1】:

我找到了问题的原因,并找到了使其正常工作的解决方案。 正如我在发布我的问题并阅读 Calum 的答案以及使用另一个项目(使用 Java)在 Mac 上进行编码的问题后已经怀疑的那样,问题的原因是 Mac OS X 使用的默认编码。当你开始@ 987654325@解释器,它将使用指定平台的默认编码。在 Mac OS X 上,这是 Macroman,在 Windows 上可能是 CP1252。您可以通过在 scala 解释器中键入以下命令来检查这一点:

scala> System.getProperty("file.encoding");
res3: java.lang.String = MacRoman

根据scala 帮助测试,可以使用-D 选项提供Java 属性。但是,这对我不起作用。我最终设置了环境变量

JAVA_OPTS="-Dfile.encoding=UTF-8"

运行scala后,上一条命令的结果会给出如下结果:

scala> System.getProperty("file.encoding")
res0: java.lang.String = UTF-8

现在,打印特殊字符可以正常工作:

print(0x20AC.toChar)               
€

所以,这不是 Scala 中的错误,而是默认编码的问题。在我看来,如果默认情况下在所有平台上使用 UTF-8 会更好。如果考虑到这一点,在我寻找答案的过程中,我在 Scala 邮件列表中遇到了一个discussion,关于这个问题。在第一条消息中,当file.encoding 报告 Macroman 时,建议在 Mac OS X 上默认使用 UTF-8,因为 UTF-8 是 Mac OS X 上的默认字符集(让我想知道为什么默认设置了 file.encoding对 Macroman 来说,这可能是 Mac OS 10 发布之前的继承?)。我不认为这个提议会成为 Scala 2.8 的一部分,因为 Martin Odersky wrote 可能最好保持 Java 中的内容(即尊重 file.encoding 属性)。

【讨论】:

  • 引用 Sun 的话:J2SE 平台规范不需要“file.encoding”属性;它是 Sun 实现的内部细节,不应由用户代码检查或修改。它也是只读的;技术上不可能支持在命令行上或在程序执行期间的任何其他时间将此属性设置为任意值。 bugs.sun.com/view_bug.do?bug_id=4163515 因此,它不受支持,可能不适用于所有 JVM,并且可能有意外的副作用。
  • 在避免 McDowell 标志问题的同时执行此操作的一种方法是将 System.out PrintStream(仍然作为原始 OutputStream 工作)与使用您想要的编码的 PrintStream 包装,然后使用它,例如“val myOut = new PrintStream(System.out, "UTF-8"); myOut.print(0x20AC.toChar)”。这应该始终有效。我会编辑这个,但我不认为我有那种事情的业力。
  • @Calum - 看看这是否适用于 Mac 很有趣;它在 Windows 上效果不佳,但可能是特定于平台的问题:illegalargumentexception.blogspot.com/2009/04/…
  • McDowell:哎呀,我只真正使用Linux。 Windows 控制台系统很可能(尽管我没有检查过)是以字符而不是字节来处理的,所以你不能在那个系统上做那种“任何事情都发生”的废话。另一方面,“任何事情都会发生”是我们在这里的部分原因;)。非常感谢您的更新。 :)
  • 谢谢,我也想知道,你的把戏奏效了。作为记录,在 Windows 上,我们必须使用 set JAVA_OPTS=-Dfile.encoding=UTF-8(没有引号)。重定向到一个文件,我想是因为 cmd.exe 使用 OEM 编码来兼容 MS-Dos。
【解决方案2】:

好的,至少部分(如果不是全部)您的问题是 128 不是欧元的 Unicode 代码点。 128(或 0x80,因为十六进制似乎是标准)是 U+0080 <control>,即它不是可打印的字符,因此您的终端无法打印也就不足为奇了。

欧元的代码点是 0x20AC(或十进制 8364),这似乎对我有用(我在 Linux 上,每晚 2.8):

scala> print(0x20AC.toChar)
€

另一个有趣的测试是打印 Unicode 雪人字符:

scala> print(0x2603.toChar)
☃

128 作为 € 显然是来自 Windows 代码页之一的扩展字符。

我让你提到的另一个角色也可以工作:

scala> 'ƒ'.toInt
res8: Int = 402

scala> 402.toChar
res9: Char = ƒ

【讨论】:

  • 关于欧元符号的错误数字,您是对的。但是,它仍然对我不起作用: scala> print(0x20AC.toChar) ?但如果它在你的夜间工作,它可能是我的系统的问题,或者它可能在较新的 Scala 2.8 版本中得到修复。我将进一步更新调查。
  • 我在今天的每晚 (2.8.0.r20300-b20091223020158) 上检查了这个,'print(0x20AC.toChar)' 打印一个问号,就像我周围的所有其他 2.8 版本一样。
  • 顺便说一句,我使用的是 OSX 10.6.2。
  • 啊,我看到这是另一个响应的 file.encoding 问题。对不起!请参阅我对您接受的答案的评论,马丁。
【解决方案3】:

对于 Windows 命令行 (cmd) 打印:

  1. set JAVA_OPTS="-Dfile.encoding=UTF-8"
  2. chcp 65001

第 2 项表示 UTF-8

如果您不想每次都打印“chcp 65001”,您可以像这样在 Windows 注册表中更改/添加值:

  1. 运行命令regedit
  2. 查找记录 [HKEY_CURRENT_USER\Software\Microsoft\Command Processor]
  3. 新 => 字符串值
  4. 名称 = “AutoRun”,数据 = “chcp 65001”(不带引号)

(见https://superuser.com/a/482117/454417

我使用 Windows 10 和 scala 2.11.8

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-27
    • 2023-03-26
    相关资源
    最近更新 更多