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


69

我正在处理一些本应为有效UTF-8但不是的数据文件,这导致解析器(不在我的控制之下)失败。我想添加一个阶段,以对UTF-8格式正确的数据进行预验证,但是我还没有找到可以帮助完成此操作的实用程序。

W3C上有一个Web服务似乎已失效,并且我发现了一个仅Windows的验证工具,该工具报告无效的UTF-8文件,但未报告要修复的行/字符。

我对可以插入并使用的工具(最好是跨平台)或可以将其作为数据加载过程一部分的ruby / perl脚本感到满意。

Answers:


96

您可以使用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。


16
在较旧的iconv版本中(例如OSX或fink),没有-o标志。但是,重定向标准输出应始终有效。
Joe Hildebrand

1
Torsten,谢谢,这在我的linux机器上完美地工作了。我找不到适用于cygwin的iconv实用程序的版本,但这不是最重要的。
伊恩·迪金森

如果您不介意通过指定以下内容丢失某些信息,也可以使用该工具清理文件:UTF-8 // TRANSLIT,UTF-8 // IGNORE甚至UTF-8 // TRANSLIT // IGNORE。
webmat 2012年

3
更好的是,将stdout和stderr重定向到/ dev / null:iconv -f UTF-8 your_file > /dev/null 2>&1; echo $?
Stratus3D

2
“假定输出编码为UTF-8”与文档相反,该文档说编码“默认为当前语言环境的编码”(GNU手册页)。如果该编码不支持输入中的任何字符,则即使输入是有效的UTF-8,也会发出“无法转换”或“输入序列非法”错误。使用iconv -f UTF-8 -t UTF-8 your_file > /dev/null以避免这些误报。
MvanGeest,

9

使用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')


5

GNU iconv怎么样库怎么样?使用iconv()函数:“输入中遇到无效的多字节序列。在这种情况下,它将errno设置为EILSEQ并返回(size_t)(-1)。* inbuf指向无效的多字节序列的开头。 ”

编辑:哦-我错过了您想要脚本语言的部分。但是对于命令行工作,iconv实用程序也应该为您验证。


0

您还可以使用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进行。


这会改变数据吗?我想通过重新编码流式传输我的数据,如果它不好并且很好,则失败,我希望数据保留在utf8中
Binyamin

1
@Binyamin:是的,它会重新编码。在上面的示例中,它只是将重新编码的数据发送到/ dev / null。但是您也可以通过管道进行第二次重新编码,将其重新放入utf8:中recode utf8/..UCS < "$FILE" | recode UCS/..utf8。遇到无效数据时,这将中止输出。
mivk

谢谢,我想我可能最终需要重新编码两次
Binyamin

0

这是bash脚本,用于检查文件是否为有效的UTF-8:

#!/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”)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.