属性文件中UTF-8的ASCII转换不一致

时间:2009-10-27 02:36:39

标签: java

有没有人知道为什么native2ascii会生成小写的十六进制代码,而Properties.store()会生成大写的十六进制代码?

示例:

保存在使用\u4FDD\u5B58时编码为Properties.store(),但在使用\u4fdd\u5b58时编码为native2ascii

有没有办法控制这个?

2 个答案:

答案 0 :(得分:3)

我不知道为什么,但我知道这无所谓(无论如何,对Java来说,它可能对你很重要)。允许Unicode转义具有较高的小写十六进制数字,因此对Java来说无关紧要(即使是混合大小写有效)。

他们不同的原因可能就像他们由两个不同的人写的一样简单。

有没有办法控制它?从我能看到的不容易。 native2ascii似乎没有任何控制输出的选项(它允许选项来控制JVM但不允许控制该级别)。

Properties.store()使用OutputStream(并且Properties.load()使用InputStream),您可能可以将其子类化以过滤Unicode转义,但这似乎是一项非常多的工作(什么看起来可疑的好处。

也许如果你能告诉我们为什么你需要这个,可能还有另一种方式。

更新1:

可以做的一件事是通过过滤器传递native2ascii输出,该过滤器将Unicode转义序列转换为大写。以下代码ucunicode.c应该能够做到这一点,尽管我只是粗略测试。只需执行:

native2ascii inputFile | ucunicode

您应该会看到\u00EF\u00BB\u00BF而非\u00ef\u00bb\u00bf的内容。

#include <stdio.h>

int main (void) {
    int count = 0;     // used for converting four hex digits after "\u".
    int chminus2 = -1; // character from two passes ago.
    int chminus1 = -1; // character from one pass ago.
    int ch;            // character for this pass.

    // Standard filter loop.

    while ((ch = getc (stdin)) != EOF) {
        if (count-- > 0) {
            // If processing Unicode escape sequence, uppercase letters.

            putchar (((ch >= 'a') && (ch <= 'f')) ? ch - 'a' + 'A' : ch);
        } else {
            // Normal processing, detect escape sequence and flag it.

            if ((chminus2 != '\\') && (chminus1 == '\\') && (ch == 'u')) {
                count = 4;
            }

            // In any case, output the character.

            putchar (ch);
        }

        // Shift characters "left".

        chminus2 = chminus1;
        chminus1 = ch;
    }
    return 0;

}

可能存在边缘情况,这不能很好地处理。我很确定它会处理所有有效输入,但可能会在\u1\\u0000之类的无效输入中断,但是,因为这意味着你的native2ascii被破坏了,你需要自己调试它们。不过这是一个好的开始。

更新2:

或者,作为最后一个解决方案,OpenJDK项目在native2ascii中有jdk\src\share\classes\sun\tools\native2ascii\的实际source files(以及其他所有不受版权保护的内容),你可以降低并编译自己(GPL2适用)。文件为Main.javaA2NFilter.javaN2AFilter.java(以及一些资源文件)。您只需更改N2AFilter.java即可致电:

String hex = Integer.toHexString(buf[i]).toUpperCase();

而不只是:

String hex = Integer.toHexString(buf[i]);

事实上,通过检查源代码,您可以看到Properties.store()(在jdk/src/share/classes/java/util/Properties.java中)使用以下函数来创建它的Unicode转义:

private static final char[] hexDigit = {
    '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'
};
private static char toHex (int nibble) {
    return hexDigit[(nibble & 0xF)];
}

这解释了为什么它会产生大写,而native2ascii产生小写。

答案 1 :(得分:1)

我只是碰到了这个,我有一个令人讨厌的原因:我只是将一个(unicode).properties文件转换为另一个(自制的XML)格式,并将导出函数转换回.properties。此函数使用Properties.store(),而原始的Unicode .properties由ant通过native2ascii转换。我现在想要比较它们产生类似的结果,因此在每个结果上应用sort并在结果上应用diff。事实上,大多数产生的不同线条都是由于这些情况在\ u-escape中存在差异。 (我想我会用一个快速的sed脚本来转换其中一个文件的情况。)


所以,这是我们的sed脚本:s/\\u([0-9A-F]{4})/\\u\L\1\E/g(更改为小写)或s/\\u([0-9A-F]{4})/\\u\U\1\E/g(更改为大写)。我不得不改变一点,因为Properties.store()还从!\!=\=:转义{ {1}}。