【问题标题】:String.getBytes("ISO-8859-1") gives me 16-bit characters on OS XString.getBytes("ISO-8859-1") 在 OS X 上给了我 16 位字符
【发布时间】:2011-01-15 04:12:49
【问题描述】:

使用 Java 6 从字符串中获取 8 位字符:

System.out.println(Arrays.toString("öä".getBytes("ISO-8859-1")));

在 Linux 上给我:[-10, 28] 但是 OS X 我得到: [63, 63, 63, -89]

当使用花哨的新 nio CharSetEncoder 类时,我似乎得到了相同的结果。我究竟做错了什么?还是苹果的错? :)

【问题讨论】:

    标签: java macos unicode ascii


    【解决方案1】:

    我设法通过将源文件保存为 UTF-8 来重现此问题,然后告诉编译器它确实是 MacRoman:

    javac -encoding MacRoman Test.java

    我原以为javac 在 OSX 上会默认为 UTF-8,但也许不是。或者,也许您正在使用 IDE,而 默认为 MacRoman。无论如何,你必须让它使用 UTF-8。

    【讨论】:

    • MacRoman 似乎是我的 OSX 系统上的默认编码。具有此文字的源文件以 UTF-8 编码,并错误地将其解析为 MacRoman。那么如何解决这个问题呢?指定 -encoding UTF-8 似乎不是一个好的选择。如果我有一些好的旧 ISO-8859-1 文件怎么办?
    • 如果您的某些文件是 ISO-8859-1,则无论如何您都必须单独编译它们并指定 that 编码。我建议您始终指定 UTF-8,用于保存和编译。如果 MacRoman 或 ISO-8859-1 文件潜入,当编译失败时你会知道;与大多数其他编码相比,诱骗 UTF-8 接受虚假数据要困难得多。
    • 我认为如果它无法以 UTF-8 格式读取文件,它会切换到 ISO-8859-1。但在我的 Linux 机器上似乎并非如此。所以'-encoding utf-8' 给出了相同的行为。我仍然对使用这个开关感觉不太舒服,但我意识到我必须在我的 OSX 盒子和类似系统上修复它。我不禁想知道是否没有全局“修复”,所以下次我遇到使用 UTF-8 字符串文字的项目时我的系统不会爆炸,而且我没有单元测试来捕捉有问题吗?
    • 平台默认编码是 Java 肮脏的小秘密之一;依赖它是永远安全的。您正在寻找的全局修复是在保存和编译源文件时始终指定编码。而且这种编码也可能是 UTF-8,因为它可以处理 Unicode 已知的每个字符,并且保证在每个平台上都得到支持。
    【解决方案2】:

    源文件的编码是什么? 63? 的代码,意思是“字符不能转换成指定的编码”。

    所以我的猜测是您将源文件复制到 Mac 并且源文件使用了 Mac java 编译器不期望的编码。 IIRC,OS X 将期望文件为 UTF-8。

    【讨论】:

      【解决方案3】:

      您的源文件通过组合字符生成“öä”。

      看看这个:

      System.out.println(Arrays.toString("\u00F6\u00E4".getBytes("ISO-8859-1")))
      

      这将像您期望的那样打印 [-10,-2​​8] (我不喜欢这样打印,但我知道这不是您的问题的重点),因为那里指定了 Unicode 代码点,刻在石头上, 并且您的文本编辑器不允许通过将 'o' 和 'a' 与变音符号组合来“玩聪明”。

      通常,当您遇到此类问题时,您可能希望使用两个 OS X Un*x 命令来了解幕后情况:filehexdump 在这种情况下非常方便。

      你想在你的源文件上运行它们,你可能想在你的类文件上运行它们。

      【讨论】:

      • 有用的小工具。那么javac怎么不知道这是一个UTF-8文件呢?
      【解决方案4】:

      也许源的字符集没有设置(因此根据系统区域设置不同)?

      你能在两个系统上运行相同的编译类吗(不重新编译)?

      【讨论】:

      • 绝对是这样。正确编译的代码将在所有支持的平台上产生相同的输出。
      【解决方案5】:

      请记住,表示字符的方法不止一种。 Mac OS X 默认使用 unicode,因此您的字符串文字实际上可能不是由两个字节表示。您需要确保从适当的传入字符集中加载字符串;例如,通过在源中指定一个 \u 转义字符。

      【讨论】:

      • 不管怎样,重音字符可以用两种方式表示;作为单个字形 (ö) 或作为组合字符 (\u0308 o)。
      • 好吧,在这种情况下,Java 文件是生成的代码。改变这些字符在文字中的编码方式是不可行的。
      猜你喜欢
      • 2013-01-19
      • 2012-09-21
      • 1970-01-01
      • 2014-01-17
      • 2012-09-29
      • 1970-01-01
      • 2016-11-26
      • 2014-01-18
      • 2017-01-04
      相关资源
      最近更新 更多