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

标签 java

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

示例:

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

有什么办法可以控制这个吗?

最佳答案

我不知道为什么,但我知道这并不重要(无论如何,对于 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 项目具有实际的 source files对于 jdk\src\share\classes\sun\tools\native2ascii\ 中的 native2ascii (以及几乎所有其他不受版权限制的内容),您可以将其下载并编译您自己(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 生成小写字母。

关于java - 属性文件中 UTF-8 的 ASCII 转换不一致,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1628487/

相关文章:

java - 使用模式在 Java 中解析字符串

java - 如何在Java中使用信号量

java - 在 Apache HttpClient 中禁用 Keep Alive

java - 仅在 chrome 浏览器中打开 url

java - 在 Activity 类中找不到方法 sendMessage(View)

java - JAVA中的隐式接口(interface)、类转换

java - 手动将 FieldError 添加到 bindingResult 时,Spring 表单输入值丢失

java - java中的数学问题试图找出我的代码有什么问题

java - Java计算一个IP地址是否在指定范围内

Java Selenium - 似乎无法选择一个元素