为什么java.lang.StringEncoding.encode忽略给定的charset使用默认值?

时间:2011-06-20 10:22:26

标签: java character-encoding

我的应用默认编码设置为“UTF-8”(启动时使用 -Dfile.encoding = UTF-8 )。 当我使用字符串类方法“getBytes(String charsetName)”和charset =“ISO-8859-1”时,似乎 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()方法。

任何线索? 谢谢

3 个答案:

答案 0 :(得分:3)

如果您没有进入if块,那么此表达式必须为false

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

这意味着:

  • se不得为null
  • 在点击true之前,第二部分必须是!,因此其中一个子表达式必须为真:
    • csn.equals(se.requestedCharsetName())
    • csn.equals(se.charsetName())

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

这不是使用VM的“默认”编码;它使用的是此线程中最后使用的编码器。

高度怀疑你发现了一个JRE错误 - 它看起来对我好。那么是什么导致你开始调试这个?你能提供一个简短但完整的程序来演示错误吗?编码到错误字节的东西?

答案 1 :(得分:0)

您需要更改

-Dfile.ecoding=UTF-8

-Dfile.encoding=UTF-8

答案 2 :(得分:0)

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

确实如此。正如解码一样,即使源确实显示它找到了charset,并将其设置在行中:

set(encoder, se);

编码或解码都不是线程安全的,因此该值必须被系统默认值覆盖,它可能在解码之前或之后设法使用设置值。

Imho,这是JRE中的一个错误。确实OP有一个拼写错误,但这并没有改变这样一个事实:如果你要求String将一个字节数组解码为UTF-8,它应该总是返回UTF-8,而不是默默地回归到其他东西。