java - Gradle / eclipse : Different behavior of german "Umlaute" when using equality?

标签 java eclipse encoding gradle aspectj

在使用 Java 的相等性检查(直接或间接)时,我遇到了德语“Umlaute”(ä、ö、ü、ß)的奇怪行为。 从 Eclipse 运行、调试或测试时,一切都按预期工作,包含“Umlaute”的输入被视为等于或不按预期处理。

但是,当我使用 Spring Boot 构建应用程序并运行它时,这些相等性检查对于包含“Umlaute”的词会失败,即对于像“Nationalität”这样的词。

通过 Jsoup 从网页中检索输入,并为某些关键字提取表格内容。页面的编码是 UTF-8,如果不是这种情况,我已经为 Jsoup 进行了转换。 源文件的编码也是UTF-8。

    Connection connection = Jsoup.connect(url)
                .header("accept-language", "de-de, de, en")
                .userAgent("Mozilla/5.0")
                .timeout(10000)
                .method(Method.GET);
    Response response = connection.execute();
    if(logger.isDebugEnabled())
        logger.debug("Encoding of response: " +response.charset());
    Document doc;
    if(response.charset().equalsIgnoreCase("UTF-8"))
    {
        logger.debug("Response has expected charset");
        doc = Jsoup.parse(response.body(), baseURL);
    }
    else
    {
        logger.debug("Response doesn't have exepcted charset and is converted");
        doc = Jsoup.parse(new String(response.bodyAsBytes(), "UTF-8"), baseURL);
    }

    logger.debug("Encoding of document: " +doc.charset());
    if(!doc.charset().equals(Charset.forName("UTF-8")))
    {
        logger.debug("Changing encoding of document from " +doc.charset());
        doc.updateMetaCharsetElement(true);
        doc.charset(Charset.forName("UTF-8"));
        logger.debug("Changed encoding of document to: " +doc.charset());
    }
    return doc;

阅读内容的示例日志输出(来自已部署的应用程序)。

Encoding of response: utf-8
Response has expected charset
Encoding of document: UTF-8

示例输入:

<tr><th>Nationalität:</th>     <td> [...] </td>    </tr>

示例代码对包含 ä、ö、ü 或 ß 的词失败但对其他词工作正常:

Element header = row.select("th").first();
String text = header.ownText();
if("Nationalität:".equals(text))
{
 // goes here in eclipse
}
else
{
 // and here in deployed spring boot app
}

从 Eclipse 运行与我缺少的构建和部署的应用程序之间有什么区别吗?这种行为还可能从何而来?我该如何解决?

据我所知,这不是(直接)编码问题,因为输入正确显示“Umlaute”... 由于这在调试时不可重现,我很难弄清楚到底出了什么问题。

编辑:虽然输入在日志中看起来不错(即变音符号正确显示),但我意识到它们在控制台中看起来不正确: <th>Nationalit├ñt:</th>

我目前正在按照 Mirko 的建议使用 Normalizer,如下所示: Normalizer.normalize(input, Form.NFC); (也用 NFD 试过)。 (SpringBoot-) 控制台和 (logback) 日志输出有何不同?

最佳答案

像变音符号这样的变音符号在 unicode 中通常可以用两种不同的方式表示:作为单代码点字符或作为两个字符的组合。这不是编码问题,它可能发生在 UTF-8、UTF-16、UTF-32 等格式中。 Java 的 equals 方法可能不会将复合字符视为等于单代码点字符,即使它们看起来完全相同。 尝试查看您正在比较的字符串的二进制表示,这样您应该能够找出差异。 您还可以使用“Character”类的方法遍历字符串并打印出所有字符的属性。也许这也有助于找出差异。

在任何情况下,如果您在“等号”的“两侧”使用 java.text.Normalizer 将文本规范化为例如 Unicode 规范化形式 C,这可能会有所帮助。这样,应该理顺上述差异,并且字符串应该按预期进行比较。

关于java - Gradle / eclipse : Different behavior of german "Umlaute" when using equality?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34445077/

相关文章:

c++ - 什么是最适合 C++ 源代码的编码

java - 对话框上的 EditText 不返回任何文本

java - 如何使用 java runtime.exec() 和 ssh 到另一台机器来启动进程

java - "java.compiler"系统属性的可能值

eclipse - GWT RPC 的 Google 示例在 Eclipse 中返回 HTTP 错误 405

java - (Eclipse) 无法显示标记/nullpointerException googlemaps api android

Java - 列出 int 数组中重复值的索引

java - rxjava 中的 throttleLatest 和 throttleLast 有什么区别?

ruby - 与 ARGF#set_encoding 的混淆

mysql - 修复 MySQL 转储中的错误编码字符