微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Java servlet 不能正确处理特殊字符如 ć

如何解决Java servlet 不能正确处理特殊字符如 ć

我有一个 java servlet,它读取由 javascript 前端发送的参数。 javascript前端使用:

escape("{€ć") which becomes "%7B%u20AC%u0107"

Java servlet 就是这样做的:

private static final Pattern JAVASCRIPT_ESCAPE_SEQUENCE= Pattern.compile("%(u[0-9a-fA-F]{4}|[0-9a-fA-F]{2})");




    static String unescape(String input) {
    Matcher matcher = JAVASCRIPT_ESCAPE_SEQUENCE.matcher(input);
    StringBuffer sb = new StringBuffer(input.length());
    while(matcher.find()) {
        String escapeSequence = matcher.group(1);
        if (escapeSequence.startsWith("u")) {
            escapeSequence = escapeSequence.substring(1);
        }
        char c = (char) Integer.parseInt(escapeSequence,16);
        //System.out.println(" converted  " + Integer.parseInt("0107",16));
        matcher.appendReplacement(sb,Character.toString(c));
    }
    matcher.appendTail(sb);
    return sb.toString();
}

String sDecodedContent = this.unescape(requestContent);

在 Java 中,变量 sDecodedContent 不是“{€ć”而是“{€?”并将它的字符串发送到后端,后端将错误的字符串存储到数据库中。 为什么 ć 没有被正确解码? 问候

解决方法

在 Java 中,变量 sDecodedContent 不是“{€ć”而是“{€?”

这是错误的。

您未能在粘贴中包含 JAVASCRIPT_ESCAPE_SEQUENCE,但假设它不是某个完全损坏的片段,c 最终将具有值 0x0107

让我们继续:

char c = 0x0107;
System.out.println(Character.toString(c));

这会按预期打印 ć,并且对该字符串的一些额外检查显示,并且毫不奇怪,代码点为 0x0107 的字符确实在您的字符串中。 Java 不是随机损坏或愚蠢设计的,所以这是有道理的。

那你为什么要观察别的东西?

因为无论 System.out 将其输出发送到什么,都只是一个流 - 一袋字节。字符集转换无处不在。 Java 认为它需要将该字符解码为的字符集编码是 A,然后将这些字节呈现回字符串并显示给您的眼球,无论是什么过程,都认为它是 B,和 A/B 不兼容。或者,它们,但是用于呈现它的字体无法处理 0x0107,并且用于指示“我没有用于此的字形”的字形是 ?。如果它不是黑色菱形的问号,则很可能是您设置的字体极其简单,或者,更有可能是编码问题。 >

那么,您是在终端中运行它吗?你配置错了。检查 bash 或 iterm 或您正在使用的任何文件的文档,并检查如何正确配置编码。 Java 正在发送正确的东西;是那之后发生的事情是错误的。

并将其发送到后端,后端将错误的字符串存储到数据库中。

同样,java 没有问题,这意味着您的数据库有问题,或者可能是 JDBC 驱动程序有问题。例如,在 mysql 上,您可能使用了数据类型 UTF8。哪个不是 UTF8(Mysql 相当 是一个糟糕的数据库,带有大量奇怪的警告,为了正确使用它,您需要了解这些警告毫无意义。我强烈建议您使用远像这样的疣更少),或者您只是将其保留为默认值,这通常是一些北欧 ISO 而不是 UTF8MB4(这是实际 UTF8 的 mysqlese)。这通常被称为“整理”,如果这有助于阅读您使用的数据库的文档。

测试所有这些东西的一个简单方法是直接到源:

String test = "\u0107";
System.out.println(test);
sendToDb(test);

如果 ć 没有被打印或者其他东西到达数据库,你知道它不是 java,因为 "\u0107" 是一个代表 ć 的文字这不可能被误解,并且不依赖于任何东西的字符集配置。这就是 Java 源文件中 \u 转义的用途:确保提供给例如错误的字符集javac 命令通过 -charset 根本不影响结果。

您会发现它正在打印 ? 并且数据库也在类似地处理这些字符串。弄乱你的终端和/或数据库的配置,直到它起作用。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。