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

我正在处理一些应该是有效的UTF-8数据文件,但不是,这会导致parsing器(不在我的控制下)失败。 我想添加一个预validationUTF-8格式良好的数据的阶段,但我还没有find一个实用程序来帮助做到这一点。

在W3C有一个networking服务似乎已经死了,我发现了一个仅用于Windows的validation工具 ,可以报告无效的UTF-8文件,但不报告要修复的行/字符。

我会很高兴与一个工具,我可以投入和使用(理想的跨平台),或ruby/ perl脚本,我可以使我的数据加载过程的一部分。

你可以使用GNU iconv:

$ iconv -f UTF-8 your_file -o /dev/null 

或者使用旧版本的iconv,例如在macOS上:

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

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

编辑 :输出编码不必指定,它将被认为是UTF-8。

使用python和str.encode |解码函数。

 >>> 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 

抛出的exception具有在.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') 

您可以使用moreutils集合中的isutf8 。

 $ apt-get install moreutils $ isutf8 your_file 

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

那怎么样gnu iconv图书馆? 使用iconv()函数:“input中遇到一个无效的多字节序列,在这种情况下,它将errno设置为EILSEQ并返回(size_t)( – 1)。* inbuf指向无效多字节序列的开头。 “

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

下面的C ++代码是基于互联网上发布的许多网站的代码。 我纠正了原始代码中的错误,并添加了检索无效字符和无效字符本身的可能性。

 ///Returns -1 if string is valid. Invalid character is put to ch. int getInvalidUtf8SymbolPosition(const unsigned char *input, unsigned char &ch) { int nb, na; const unsigned char *c = input; for (c = input; *c; c += (nb + 1)) { if (!(*c & 0x80)) nb = 0; else if ((*c & 0xc0) == 0x80) { ch = *c; return (int)c - (int)input; } else if ((*c & 0xe0) == 0xc0) nb = 1; else if ((*c & 0xf0) == 0xe0) nb = 2; else if ((*c & 0xf8) == 0xf0) nb = 3; else if ((*c & 0xfc) == 0xf8) nb = 4; else if ((*c & 0xfe) == 0xfc) nb = 5; na = nb; while (na-- > 0) if ((*(c + nb) & 0xc0) != 0x80) { ch = *(c + nb); return (int)(c + nb) - (int)input; } } return -1; }