如何检查一个文件是否有效的 UTF-8?

我正在处理一些数据文件,这些文件应该是有效的 UTF-8,但实际上并非如此,这会导致解析器(不在我的控制之下)失败。我想为 UTF-8格式良好性添加一个预验证数据的阶段,但是我还没有找到一个实用程序来帮助完成这项工作。

W3C 上有一个 网上服务似乎已经死了,我发现一个 Windows 验证的 工具报告了无效的 UTF-8文件,但是没有报告要修复的行/字符。

如果有一个工具我可以使用(理想情况下是跨平台的) ,或者一个 Ruby/perl 脚本,我可以将其作为我的数据加载过程的一部分,我会很高兴。

83564 次浏览

使用 python 和 str.encode | decode 函数。

>>> a="γεια"
>>> a
'\xce\xb3\xce\xb5\xce\xb9\xce\xb1'
>>> b='\xce\xb3\xce\xb5\xce\xb9\xff\xb1' # note second-to-last char changed
>>> print b.decode("utf_8")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/local/lib/python2.5/encodings/utf_8.py", line 16, in decode
return codecs.utf_8_decode(input, errors, True)
UnicodeDecodeError: 'utf8' codec can't decode byte 0xff in position 6: unexpected code byte

抛出的异常在其. args 属性中具有请求的信息。

>>> try: print b.decode("utf_8")
... except UnicodeDecodeError, exc: pass
...
>>> exc
UnicodeDecodeError('utf8', '\xce\xb3\xce\xb5\xce\xb9\xff\xb1', 6, 7, 'unexpected code byte')
>>> exc.args
('utf8', '\xce\xb3\xce\xb5\xce\xb9\xff\xb1', 6, 7, 'unexpected code byte')

Gnu Iconv库怎么样?使用 iconv ()函数: “在输入中遇到无效的多字节序列。在本例中,它将 errno 设置为 EILSEQ 并返回(size _ t)(- 1)。* inbuf 指向无效多字节序列的开头。”

我错过了你想要脚本语言的部分。但是对于命令行工作,Iconv实用程序也应该为您进行验证。

你可以使用 GNU iconv:

$ iconv -f UTF-8 your_file -o /dev/null; echo $?

或者使用旧版本的 iconv,比如 macOS:

$ iconv -f UTF-8 your_file > /dev/null; echo $?

如果文件能够成功转换,则该命令返回0,如果不能成功转换,则返回1。此外,它还会打印出发生无效字节序列的字节偏移量。

编辑 : 不需要指定输出编码,假设它是 UTF-8。

您可以从 Moreutils集合中使用 Isutf8

$ apt-get install moreutils
$ isutf8 your_file

在 shell 脚本中,使用 --quiet开关并检查退出状态,对于有效的 utf-8文件,退出状态为零。

您还可以使用 recode,如果它尝试解码 UTF-8并遇到无效字符,那么它将退出并出现错误。

if recode utf8/..UCS < "$FILE" >/dev/null 2>&1; then
echo "Valid utf8 : $FILE"
else
echo "NOT valid utf8: $FILE"
fi

这将尝试重新编码到 通用字符集(UCS),这在有效的 UTF-8中始终是可能的。

下面是用于检查文件是否有效的 UTF-8的 bash 脚本:

#!/bin/bash


inputFile="./testFile.txt"


iconv -f UTF-8 "$inputFile" -o /dev/null


if [[ $? -eq 0 ]]
then
echo "Valid UTF-8 file.";
else
echo "Invalid UTF-8 file!";
fi

描述:

  • --from-code-f编码(从编码转换字符)
  • --to-code-t编码(将字符转换为编码,不需要指定,假定为 UTF-8)
  • --output-o文件(指定输出文件‘而不是 stdout’)