ral*_*len 4 python encoding cjk
我是一名初学者,无法在Python 2.7中将数十个(简体)中文字符解码为UTF-8的数十个CSV文件.
我不知道输入文件的编码,所以我尝试了所有可能的编码 - GB18030,UTF-7,UTF-8,UTF-16和UTF-32(LE&BE).此外,为了更好的衡量,GBK和GB3212,虽然这些应该是GB18030的子集.当UTF到达第一个汉字时,它们都会停止.除GB18030外,其他编码在第一行的某处停止.我认为这将是解决方案,因为它读取了前几个文件并解码它们.我的部分代码,逐行阅读,是:
line = line.decode("GB18030")
Run Code Online (Sandbox Code Playgroud)
我尝试解码的前两个文件工作正常.在第三个文件的中途,Python吐出来
UnicodeDecodeError: 'gb18030' codec can't decode bytes in position 168-169: illegal multibyte sequence
Run Code Online (Sandbox Code Playgroud)
在这个文件中,大约有一百万行有大约5个这样的错误.
我在文本编辑器中打开输入文件并检查哪些字符给出了解码错误,前几个字符在CSV文件的特定列中都有欧元符号.我相信这些是拼写错误,所以我只想删除欧元字符.我想逐个检查编码错误的类型; 我想摆脱所有的欧元错误,但不要只是忽略别人,直到我先看看它们.
编辑:我用的chardet
是GB2312编码,所有文件的置信度为.99.我尝试使用GB2312解码,它给出了:
UnicodeDecodeError: 'gb2312' codec can't decode bytes in position 108-109: illegal multibyte sequence
Run Code Online (Sandbox Code Playgroud)
""......"GB18030.我认为这将是解决方案,因为它通读了前几个文件并将它们解码得很好.""" - 请解释一下你的意思.对我来说,成功解码有两个标准:首先,raw_bytes.decode('some_encoding')没有失败,其次,显示的结果unicode在特定语言中是有意义的.当使用latin1
aka 解码时,Universe中的每个文件都将通过第一个测试iso_8859_1
.东亚语言中的许多文件通过第一次测试gb18030
,因为大多数中文,日文和韩文中经常使用的字符使用相同的双字节序列块进行编码.你做了多少第二次测试?
不要在IDE或文本编辑器中查看数据.在Web浏览器中查看它; 他们通常会更好地检测编码.
你怎么知道它是欧元字符?通过查看使用什么编码解码原始字节的文本编辑器的屏幕?CP1252?
你怎么知道它包含汉字?你确定它不是日本人吗?韩国人?你是从哪里得到的?
中国文件在香港,台湾,也许是澳门,以及大陆以外的地方使用big5
或big5_hkscs
编码 - 试试.
无论如何,请听取马克的建议并指出chardet
它; chardet
如果文件足够大并且正确编码中文/日文/韩文,通常可以很好地检测所使用的编码 - 但是如果有人使用单字节字符集在文本编辑器中手动编辑文件,那么一些非法的字符可能导致用于其他99.9%字符的编码无法被检测到.
您可能希望print repr(line)
从文件中说出5行并将输出编辑到您的问题中.
如果文件不是保密文件,您可以将其下载.
该文件是否在Windows上创建?你是如何用Python阅读的?(显示代码)
OP评论后更新:
记事本等不要试图猜测编码; "ANSI"是默认值.你必须告诉它该怎么做.什么您呼叫的欧元字符是原始字节"\ X80"通过使用环境的默认编码编辑器解码 - 在常规疑似存在"CP1252".不要使用这样的编辑器来编辑您的文件.
早些时候你在谈论"前几个错误".现在你说你总共有5个错误.请解释.
如果该文件确实是几乎正确GB18030,你应该能够通过行的文件行进行解码,并且当你得到这样的错误,陷阱吧,打印错误消息,从消息中提取的字节偏移,印刷再版(two_bad_bytes) ,并继续前进.我对\x80
出现的两个字节中的哪一个非常感兴趣.如果它根本没有出现,"欧元字符"不是您问题的一部分.注意,它\x80
可以在gb18030文件中有效出现,但仅作为以\x81
to 开头的2字节序列的第2个字节出现\xfe
.
在尝试修复问题之前,最好先了解问题所在.尝试通过在"ANSI"模式下使用记事本等来解决它并不是一个好主意.
关于你如何确定gb18030解码的结果是有意义的,你一直非常腼腆.特别是我会密切仔细检查线路,其中GBK失败,但GB18030"作品" - 必须有没有一些极为罕见的中国文字,或者一些非中国非ASCII字符...
这是一个更好的方法来检查损坏的建议:解码每个文件raw_bytes.decode(encoding, 'replace')
并将结果(以utf8编码)写入另一个文件.按错误计算错误result.count(u'\ufffd')
.使用您用于确定gb18030解码有意义的任何内容查看输出文件.U + FFFD角色应该在黑色钻石内显示为白色问号.
如果您认为可以丢弃不可解码的部分,最简单的方法是 raw_bytes.decode(encoding, 'ignore')
更多信息后更新
所有这些\\
都令人困惑.看来,"渐字节"涉及repr(repr(bytes))
,而不是只repr(bytes)
......在互动提示,请执行bytes
(你会得到一个内隐再版()),或print repr(bytes)
(这不会得到隐再版())
空格:我假定你的意思是'\xf8\xf8'.decode('gb18030')
为你解读一下作为某种全角空格,并且该解释通过目测使用一些难以名状的浏览器软件来完成.那是对的吗?
实际上,'\xf8\xf8'.decode('gb18030')
- > u'\e28b'
.U + E28B位于Unicode PUA(专用区)中."空白空间"可能意味着观看者软件在其正在使用的字体中不具有U + E28B的字形.
也许文件的来源是故意使用PUA对于不是在标准GB18030字符,或注释,或用于传输pseudosecret信息.如果是这样,你将需要求助于解码手鼓,这是俄罗斯近期研究报道的一个分支.
替代方案:cp939-HKSCS理论.根据香港政府的说法,HKSCS big5代码FE57曾被映射到U + E28B,但现在映射到U + 28804.
"欧元":你说"""由于数据我不能分享整行,但我所谓的欧元字符是:\ xcb\xbe\x80\x80"[我假设\
是从一开始就省略了,而且"
是文字的].当它出现时,"欧元字符"总是在我不需要的列中,所以我希望只使用"忽略".不幸的是,由于"欧元字符"紧挨着文件中的引号,有时"忽略"会删除欧元字符以及[as]引号,这会给csv模块确定列"""
如果您能够显示这些\x80
字节与引号和中文字符相关的位置模式,那将非常有用 - 只需显示十六进制就可以保持可读性,并隐藏您的机密数据,例如使用C1 C2表示"两个字节"我肯定代表一个中国人".例如:
C1 C2 C1 C2 cb be 80 80 22 # `\x22` is the quote character
Run Code Online (Sandbox Code Playgroud)
请提供(1)的例子,其中"不会被'替换'或'忽略'(2)丢失.在你唯一的例子中,"不会丢失:
>>> '\xcb\xbe\x80\x80\x22'.decode('gb18030', 'ignore')
u'\u53f8"'
Run Code Online (Sandbox Code Playgroud)
向您发送一些调试代码的提议(参见下面的示例输出)仍然是开放的.
>>> import decode_debug as de
>>> def logger(s):
... sys.stderr.write('*** ' + s + '\n')
...
>>> import sys
>>> de.decode_debug('\xcb\xbe\x80\x80\x22', 'gb18030', 'replace', logger)
*** input[2:5] ('\x80\x80"') doesn't start with a plausible code sequence
*** input[3:5] ('\x80"') doesn't start with a plausible code sequence
u'\u53f8\ufffd\ufffd"'
>>> de.decode_debug('\xcb\xbe\x80\x80\x22', 'gb18030', 'ignore', logger)
*** input[2:5] ('\x80\x80"') doesn't start with a plausible code sequence
*** input[3:5] ('\x80"') doesn't start with a plausible code sequence
u'\u53f8"'
>>>
Run Code Online (Sandbox Code Playgroud)
尤里卡: - 有时会失去引用字符的可能原因 -
看来gb18030
解码器替换/忽略机制中存在一个错误:\x80
不是有效的gb18030前导字节; 当检测到时,解码器应尝试与NEXT字节重新同步.但是它似乎忽略了\x80
AND和后面的字节:
>>> '\x80abcd'.decode('gb18030', 'replace')
u'\ufffdbcd' # the 'a' is lost
>>> de.decode_debug('\x80abcd', 'gb18030', 'replace', logger)
*** input[0:4] ('\x80abc') doesn't start with a plausible code sequence
u'\ufffdabcd'
>>> '\x80\x80abcd'.decode('gb18030', 'replace')
u'\ufffdabcd' # the second '\x80' is lost
>>> de.decode_debug('\x80\x80abcd', 'gb18030', 'replace', logger)
*** input[0:4] ('\x80\x80ab') doesn't start with a plausible code sequence
*** input[1:5] ('\x80abc') doesn't start with a plausible code sequence
u'\ufffd\ufffdabcd'
>>>
Run Code Online (Sandbox Code Playgroud)