有没有办法使用java查找文件编码类型(UTF-8或ANSI或Cp1252或其他)

问题描述 投票:0回答:2

我必须阅读一些 html 文件。如果我使用 UTF-8 作为读取和写入文件的字符集,则 html 页面中会显示一些垃圾字符。看起来实际的文件是 ANSI 编码的,因为我使用 UTF-8 来读取和写入文件,很少有空格显示为带问号的黑色菱形。

有没有办法找到用于读/写特定文件的编码/字符集?

java encoding detection
2个回答
1
投票

不,这在数学上是不可能的。文件只是字节包,大多数编码都使得任何字节都有意义。如果没有使用人工智能装置来分析您使用正确的编码读取它的可能性(寻找混合来自不同 unicode 平面等的字符的单词),因此无法确定。

可以最终确定某些文件绝对不是 UTF_8(或者已损坏),因为某些字节序列不能出现在对某些字符进行 UTF-8 编码时产生的字节流中。然而,这也不是很有用:你不能得出结论:哦!必须是UTF-8!基于缺乏这些无效序列。

你有一些选择

正确的方法

当您保存这些 HTML 文件时,即选择编码时(HTML 从网络服务器接收并加载到浏览器内存中,并且已使用 HTTP 响应标头“Content-Type”中列出的字符集从字节解码为字符',然后你要求浏览器将其保存到一个文件中,此时浏览器需要选择一种编码),或者已知(用于保存 HTML 的工具直接保存 HTML“原始”,就像发送时一样)通过 HTTP 连接,但作为执行此操作的一部分,该工具知道编码,因为 HTTP 服务器在“Content-Type”标头中发送了编码),因此 that 是存储此信息的最佳时机,或者选择一种众所周知的编码(UTF-8 是个好主意)。

因此,返回到设法保存这些文件的软件和/或进程并从源头修复它:要么保存编码,要么确保 HTML 文件以 UTF-8 保存,无论您使用什么 HTTP 服务器从发送时获取此 HTML。

黑客方式

拿起放大镜,戴上你最好的帽子,穿上你的夏洛克·福尔摩斯。

通常的策略是打开十六进制编辑器,然后转到文件中看到菱形或意外字符的位置,然后查看字节序列。特别是如果它是一个有点“众所周知”的西方非 ASCII 字符,例如 é 或 ö,那么在网络上搜索您在那里看到的字节,通常您会找到它。查找十进制值 128 或更高的十六进制值,以 8、9 或字母开头的值 - 因为下面的值是 ASCII 并且几乎所有编码都以相同的方式对它们进行编码,因此对于区分编码。

例如,如果您搜索

0xE1 0xBA 0x9E
,第一个搜索会将您带到 此页面,向下滚动到 0xe1 0xBA 0x9e,它会显示:这是代码点 1E9E 的 UTF-8 版本,升号 s (ß - 通用在德国)。如果这在文本中有意义,我们就明白了。我们需要人工智能来进行文本分析,以确定它是否有意义。我没有,所以我们需要一个人工智能。换句话说,你的大脑必须完成这项工作。看看它:如果在替换 ß 后,文本显示为
Last Name: Boßler
,那么您显然明白了 - Boßler 是一个德国姓氏,也是德国的一座山。如果您不确定,请再次进行网络搜索来救援。

有时您必须弄清楚它应该是什么字符,并将其包含在搜索中。例如,如果您检查文件并看到

0xDF
并且您知道 ß 必须存在,则搜索
0xDF ß
,然后您会看到 此页面,其中显示了大量编码以及它们如何存储 ß。只有少数将其存储为 0xDF:它是某种 ISO-8859 变体,或 Cp-125x 变体(又名 windows-125x),并且您已成功排除 IBM852。没有办法知道它实际上是 ISO-8859 或 Cp-125 的哪个变体;你需要更多奇怪的字符,并希望你能找到一个你知道它应该是什么的字符,并且这些字符在它们之间的编码方式不同(不太可能;它们非常相似)。

最终您很可能知道它是几种编码之一,因为通常有多种编码都会产生完全相同的字节序列。事实上,如果您有全 ASCII 字符,则可能有数千的编码。


0
投票
enter code here
import org.apache.tika.parser.txt;

CharsetDetector dt=new CharsetDetector();
byte[] in;
try {
in = Files.readAllBytes(Paths.get(iFile.toUri()));
CharsetDetector dt1=dt.setText(in);
String charset=dt1.detect().getName(); 
}
© www.soinside.com 2019 - 2024. All rights reserved.