在使用 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/