【问题标题】:Why java.lang.StringEncoding.encode ignore given charset to use default one?为什么 java.lang.StringEncoding.encode 忽略给定的字符集以使用默认字符集?
【发布时间】:2011-09-18 13:57:45
【问题描述】:

我的应用默认编码设置为“UTF-8”(在启动时使用 -Dfile.encoding=UTF-8)。 当我使用带有 charset="ISO-8859-1" 的 String 类方法“getBytes(String charsetName)”时,似乎 StringCoding.encode 最终使用默认字符集 (UTF-8) 而不是给定的 (ISO-8859-1)。

由于未知原因,我可以在此方法上逐步调试,但我无法检查内部元素值(仅限名为 arg0、arg1 ...的参数)

在 java 1.6.10 中,StringCoding.encode 是这样写的:

static byte[] encode(String charsetName, char[] ca, int off, int len)
    throws UnsupportedEncodingException
{
    StringEncoder se = (StringEncoder)deref(encoder);
    String csn = (charsetName == null) ? "ISO-8859-1" : charsetName;
    if ((se == null) || !(csn.equals(se.requestedCharsetName())
                  || csn.equals(se.charsetName()))) {
        se = null;
        try {
        Charset cs = lookupCharset(csn);
        if (cs != null)
            se = new StringEncoder(cs, csn);
        } catch (IllegalCharsetNameException x) {}
        if (se == null)
            throw new UnsupportedEncodingException (csn);
        set(encoder, se);
    }
    return se.encode(ca, off, len);
}

通过逐步调试,我从不进入 if 块,然后没有使用我的 ISO-8859-1 字符集创建新的 StringEncoder。最后调用 Charset.defaultCharset() 方法。

有什么线索吗? 谢谢

【问题讨论】:

  • -Dfile.ecoding=UTF-8 实际上是这样拼写的吗?如果是这样,它应该是 -Dfile.encoding=UTF-8
  • 您能否发布一个发生这种情况的完整示例 (SSCCE)?

标签: java character-encoding


【解决方案1】:

encode 永远不应忽略给定的字符集以恢复为 -Dfile.encoding 中给定的字符集。

确实如此。顺便说一句,解码也是如此,即使源确实表明它找到了字符集,并将其设置在行中:

set(encoder, se);

encode 和 decode 都不是线程安全的,因此该值必然会被系统默认覆盖,但它可能在 decode 设法使用设置值之前或之后。

恕我直言,这是 JRE 中的错误。确实,OP 有一个错字,但这并没有改变这样一个事实,即如果您要求 String 将字节数组解码为 UTF-8,它应该始终返回 UTF-8,而不是默默地退回到其他东西。

【讨论】:

    【解决方案2】:

    如果你没有进入if 块,那么这个表达式一定是假的

    (se == null) || !(csn.equals(se.requestedCharsetName())
                      || csn.equals(se.charsetName()))
    

    这意味着:

    • se 不能为空
    • 第二部分必须是true,然后才能点击!,因此以下子表达式之一必须为真:
      • csn.equals(se.requestedCharsetName())
      • csn.equals(se.charsetName())

    换句话说,se 已经适合您请求的字符集名称。

    这没有使用虚拟机的“默认”编码;它正在使用此线程中最后使用的编码器。

    高度怀疑您是否发现了一个 JRE 错误 - 我觉得它没问题。那么是什么导致你开始调试呢?你能提供一个简短但完整的程序来演示使用它的错误吗?编码错误的字节?

    【讨论】:

    • 当然不是jre bug,肯定有什么我没看懂的地方。
    • @Redmat:那么你有一个简短但完整的程序来演示 String.getBytes("ISO-8859-1") 给出错误的结果吗?
    • 我正在研究它 :) 实际上,对于一个非常短的程序,我无法重现该错误。我认为StringEncoder se = (StringEncoder)deref(encoder);这行是我的问题的关键。
    • 我进入这个的原因是因为我的应用程序和目标字符集的文件编码设置为 UTF-8 - 对于我必须编码的功能 - 使用 ISO-8859-1 ,我在将结果写入文件时获得了不可读的字节。如果我用 PSPad hex 打开这个文件,很多字节会被 0x3F 替换,这对应于“?”在 ISO-8859-1 中
    • @Redmat:这表明您的字符串中有在 ISO-8859-1 中无法表示的字符,这是完全可行的......
    【解决方案3】:

    你需要改变

    -Dfile.ecoding=UTF-8

    -Dfile.encoding=UTF-8

    【讨论】:

      猜你喜欢
      • 2011-01-04
      • 2011-09-17
      • 1970-01-01
      • 1970-01-01
      • 2019-02-07
      • 2021-08-03
      • 2011-05-04
      • 2023-03-18
      • 1970-01-01
      相关资源
      最近更新 更多