如何在python 3.6中打开混合编码的unicode文件?

2024-09-27 21:31:09 发布

您现在位置:Python中文网/ 问答频道 /正文

我从未记录的资源接收文件,其中可能包含如下数据:

16058637149881541301278JA1コノマンガガスゴイヘンシュウブ4
#recordsWritten:1293462

上面只是一个例子,我正在处理的文件包含各种不同的语言(以及编码)。然后,我将使用Python 3.6(我从Python 2升级到Python 3的继承代码库)打开我的文件,代码如下:

import os

f = open(file_path, "r")

f.seek(0, os.SEEK_END)
f.seek(f.tell() -40, os.SEEK_SET)
records_str = f.read()
print(records_str)

使用此代码,我收到一个:UnicodeDecodeError: 'utf-8' codec can't decode byte 0x82 in position 0: invalid start byte

如果我将其更改为包含编码:

f = open(file_path, "r", encoding='utf-8'),我收到了相同的错误

将编码更改为utf-16会导致it打印:

랂菣Ꚃ菣Ɩȴ⌊敲潣摲坳楲瑴湥ㄺ㤲㐳㈶ਂ

这似乎是错误的

将其切换为以二进制模式打开文件:f = open(file_path, "rb")会导致其输出:

b'\x82\xb7\xe3\x83\xa5\xe3\x82\xa6\xe3\x83\x96\x014\x02\n#recordsWritten:1293462\x02\n'

现在这稍微好一点,但是,当我最终开始处理文件时,我不想将\x82\xb7\xe3\x83\xa5\添加到我的数据库中,我宁愿添加ガガスゴイヘンシ。那么,有没有一种方法可以处理Unicode编码的文件?我还研究了Mozilla chardet项目以尝试确定编码,但在下面的代码示例中,它认为该文件是utf-8编码的


Tags: 文件path代码编码osseekopenutf
2条回答

如果不知道文件中的实际字节,我们所能做的就是推测

如果文件在整个过程中没有使用单一编码,那么实际上就没有办法以编程方式处理它。您必须将其划分为多个部分,并分别使用对该序列正确的编码对每个部分进行转换。这几乎肯定需要手工操作,即使只是为了在不同编码的部分之间建立边界

接下来,您可能希望将所有内容转换为单一编码;我的建议是UTF-8。它应该能够容纳任何可以让Python首先识别为有效字符串的内容

作为一个粗略的示例,如果您知道您提供的示例使用纯7位ASCII表示拉丁部分,EUC-JP表示日语字符,那么可以尝试一下

with open(filename, 'rb') as filebytes:
    raw_bytes = filebytes.read()
string = raw_bytes[0:26].decode('ascii') + \
    raw_bytes[26:54].decode('euc-jp') + \
    raw_bytes[54:].decode('ascii')

我根据您提供的字符串实验性地确定了字符范围;如果我猜错了日语文本使用的编码(特别是),那么它们可能与您的实际数据不符

观察我们如何从用rb打开的文件句柄中读取bytes,Python在读取它们时不会尝试应用任何字符编码。但是如果我们想把它们变成一个字符串,我们当然必须用正确的编码分别对它们进行编码

如果将{}插入UTF-8序列的中间,错误消息并不一定意味着数据实际上不是UTF-8,只是无法找到确切的位置并获得有用的解码。“无效开始字节”表示这不能是有效UTF-8字符串的开始

如果您只需要检索文件的最后一行,可以只读取整个文件并删除最后一行,或者use ^{}/ ^{} until you find a position you can safely seek to. ,或者只读取部分或全部文件作为bytes,然后只解码最后一行

import os

with open(file_path, "rb") as f:  # notice "b" in "rb"
    f.seek(0, os.SEEK_END)
    f.seek(f.tell() -40, os.SEEK_SET)
    records_bytes = f.read()
records_str = records_bytes.split(b'\n')[-2].decode('ascii')
print(records_str)

我们使用[-2]的前提是文件末尾包含一个最终换行符(即,它是一个格式良好的文本文件),因此[-1]只是一个空字符串,这将检索最后一个实际行

(将此作为一个单独的答案发布,以免污染我的另一个答案,我希望这对未来的访问者可能更有用。)

相关问题 更多 >

    热门问题