欢迎各位兄弟 发布技术文章

这里的技术是共享的

You are here

python zip zip_ref 解压后 里面的中文文件名变成了乱码 通义 chatgpt 有大用 有大大用

def unzip_file(zip_file_path, extract_to):    with zipfile.ZipFile(zip_file_path, 'r') as zip_ref:        # 确保覆盖已存在的文件        for member in zip_ref.namelist():            zip_ref.extract(member, path=extract_to, pwd=None) python 解压后 里面的中文文件名变成了乱码

在处理包含中文文件名的ZIP文件时,如果解压后出现乱码,通常是因为ZIP文件中的文件名使用了CP437编码而不是UTF-8。Python 的 zipfile 模块默认情况下期望文件名是用UTF-8编码的,这在很多情况下是正确的,但是如果ZIP文件是用Windows资源管理器创建的,那么它可能会使用本地系统编码(例如GBK)来编码文件名。

为了正确解压这类ZIP文件并保留其中文文件名,你需要手动指定正确的编码格式。下面是一个修改后的示例函数,它尝试以'utf-8'和'gbk'两种编码方式读取文件名:

python
深色版本
import zipfile

def unzip_file(zip_file_path, extract_to):
    with zipfile.ZipFile(zip_file_path, 'r') as zip_ref:
        # 遍历压缩包内的所有文件
        for info in zip_ref.infolist():
            # 尝试使用'utf-8'解码文件名
            try:
                # 有些ZIP文件可能使用utf-8编码
                info.filename = info.filename.encode('cp437').decode('utf-8')
            except UnicodeDecodeError:
                # 如果失败,则尝试使用'gbk'解码(适用于简体中文环境)
                try:
                    info.filename = info.filename.encode('cp437').decode('gbk')
                except UnicodeDecodeError:
                    pass  # 如果两种编码都失败,则保持原样

            # 解压文件
            zip_ref.extract(info, path=extract_to)

# 使用示例
# unzip_file('path/to/your.zip', 'path/to/extract/directory')

这段代码首先尝试将文件名从CP437编码转换为UTF-8。如果遇到UnicodeDecodeError错误(意味着转换失败),则尝试将编码转换为GBK。如果两种方法都不起作用,就保留原来的文件名不变。这样可以有效地解决由于编码不匹配导致的中文文件名乱码问题。



CP437编码 是什么

CP437,有时也称为IBM扩展字符集(IBM Extended Character Set),是最早由IBM为最初的IBM PC设计的一种字符编码。它被用作原始的MS-DOS代码页,并且在早期的个人电脑中广泛用于文本显示。CP437包括了ASCII标准中的128个字符(0到127),并扩展了额外的128个图形字符和特殊符号(128到255),这些额外的字符包括各种欧洲语言所需的字母、货币符号以及一些几何形状和线条绘制字符。

尽管CP437在历史上很重要,但随着软件和互联网的发展,它已经被更现代的编码格式如ISO 8859、Windows-1252和UTF-8所取代。然而,在某些特定场景下,比如处理一些老的ZIP文件时,你可能会遇到使用CP437编码存储文件名的情况。这是因为ZIP文件格式最初默认采用这种编码来存储文件名信息。

在Python的zipfile库中,默认情况下假设ZIP文件内部的文件名是用UTF-8编码的。但是,如果ZIP文件是由使用CP437编码的系统创建的(例如旧版本的Windows),则需要手动将编码转换为正确的格式以正确显示非英文字符,如中文文件名。这就是为什么在处理包含非英文文件名的ZIP文件时,可能需要特别注意编码问题的原因。



info.filename = info.filename.encode('cp437').decode('gbk') 详解

在Python中,info.filename = info.filename.encode('cp437').decode('gbk') 这行代码的目的是尝试修正ZIP文件中文件名编码不匹配的问题。具体来说,它试图将一个使用CP437编码的字符串转换为正确的GBK编码(主要用于简体中文环境)的字符串,以便正确显示包含中文字符的文件名。

逐部分解释

  1. info.filename.encode('cp437')

  • info.filename 是从ZIP文件中读取的文件名字符串。

  • .encode('cp437') 将这个字符串按照CP437编码进行编码,结果是一个字节序列(bytes)。这是因为假设原始ZIP文件中的文件名是以CP437编码存储的。这一步操作是为了将可能被错误解释的字符串重新编码成原始的字节表示形式。

  • .decode('gbk')

    • 接着,.decode('gbk') 将上述步骤得到的字节序列按照GBK编码进行解码,将其转换回字符串格式。这里假设实际的文件名是用GBK编码的。如果这个假设成立,那么这样处理后得到的字符串将会以正确的字符集显示中文文件名。

    为什么这样做?

    • 在一些旧版软件或系统生成的ZIP文件中,文件名可能不是以UTF-8而是以系统的默认编码(例如,在简体中文版Windows上可能是GBK)进行编码的。然而,Python的zipfile模块默认情况下会尝试以UTF-8来解读这些文件名,这就可能导致非英文字符(如中文字符)显示为乱码。

    • 通过先将字符串编码为CP437再解码为GBK,我们实际上是在绕过Python默认的UTF-8解读方式,手动指定一种不同的编码转换路径,从而试图恢复出正确的文件名。

    注意事项

    这种方法并非总是有效,因为:

    • 并非所有ZIP文件都使用CP437编码来存储文件名;不同系统和工具可能会使用不同的编码。

    • 如果ZIP文件中的文件名实际上是用其他编码(而不是GBK)编写的,那么这种方法可能会失败,导致新的乱码或其他问题。

    因此,通常的做法是在尝试这种强制转换之前,首先检查是否可以以UTF-8正确解码文件名,并且准备好处理多种编码情况。



    普通分类: