使用启发式方法修复错误编码文本的 Java 库

Posted

技术标签:

【中文标题】使用启发式方法修复错误编码文本的 Java 库【英文标题】:Java library to fix incorrectly encoded text using heuristics 【发布时间】:2012-12-02 21:03:02 【问题描述】:

我正在处理一个外部 Web 服务,它给我错误编码(和或损坏)的字符串 (UTF-8),这些字符串很可能是 ISO LATINWINDOWS-1252,但现在是 UTF-8(和或ISO/WINDOWS/UTF-8 的混合物)。可爱的 A 帽子 (Â) 比比皆是。

我显然无法修复外部 Web 服务如何存储其字符串,从而导致信息丢失。因此,我所知道的 100% 翻译的希望是不可能的。

但我希望有人用 Java 编写了一个启发式字符映射库(不太可能有人会键入 A 帽子)。

如果不是我想我可以移植这些家伙的 php 代码:https://***.com/a/3521340/318174

更新和解释: 像@VGR 这样的简单转换将不起作用。我没有原始字节。数据在端点转换不正确(SOAP 服务器可能getBytes(/*with out correct encoding*/) 已完成,或者数据可能以不正确的格式存储)。当您在 Java 中将字节转换为字符串时,除非编码在任何地方都相同,否则不会保留数据。如果您想到ASCII UTF-8 之类的东西,这很容易理解。使用Windows-1252ISO Latin 会更复杂,因为数据不会丢失但经常混淆。那是因为这些编码可以是两个字节,而不是UTF-8 的子集。

如果您不相信我,您可以尝试使用各种编码来回执行getBytes(),并且会看到数据损坏和数据丢失。

【问题讨论】:

我不应该打扰我,但是当有人投票结束而不写评论时,我总是很烦。 【参考方案1】:

我可能误解了错误编码数据的性质,但 PHP 代码对我来说似乎有点矫枉过正。如果您有作为单个字符传递的 UTF-8 字节,您应该可以这样做:

String fix(String s) 
    byte[] bytes = s.getBytes(Charset.forName("windows-1252"));
    return new String(bytes, StandardCharsets.UTF_8);

【讨论】:

这不起作用,因为数据已经损坏。如果我有原始字节,那将起作用。相信我,您列出的内容是我非常清楚的。 @AdamGent 这就是 PHP 代码的作用……尽管它应该使用 Windows-1252 而不是 ISO-8859-1。你能举例说明你拥有什么以及它应该是什么吗? 你是对的;代码更新。我在想所有 UTF-8 字节也是有效的 ISO-8859-1 字符,但事实并非如此。 @Esailija 以上根本不是 PHP 代码在做什么。 PHP 代码正在根据一些启发式映射替换字符字节。这样做的原因是因为代码假设混合了 2 字节拉丁/窗口代码和潜在的 4 字节 UTF-8,这是我的问题。上面的 Java 代码将字节放入不是 UTF-8 的 Unicode 中,然后从 Unicode 转换为您想要的基于巨大映射表的任何字符编码。 我不清楚为什么这还不够。如果您知道应该对原始错误编码字节进行编码的编码,那么使用已知字符集对其进行解码是完全安全和可靠的。与不带参数调用 String.getBytes 不同,带参数调用 String.getBytes 要可靠得多,并且可以保证产生可预测的结果。不会丢失任何信息。问题是您的服务无法知道原始编码应该是什么?

以上是关于使用启发式方法修复错误编码文本的 Java 库的主要内容,如果未能解决你的问题,请参考以下文章

如何修复 OptaPlanner 中的构造启发式?

markdown 错误:使用GraphQL接口时的启发式错误

来自《星际迷航》的灵感启发

深受 Pandas 启发的 JavaScript 开源库 — Danfo.js

深受 Pandas 启发的 JavaScript 开源库 — Danfo.js 现已推出!

深受 Pandas 启发的 JavaScript 开源库 — Danfo.js