为什么有些.zip压缩包在Windows下直接打开是空的

文章探讨了Windows系统下空.zip文件的成因,包括路径以/开头、特殊字符编码问题。解决方案涉及文件转换,确保遵循标准并修正编码问题,以便在Windows上正常打开。
摘要由CSDN通过智能技术生成

我们最近有遇到了一些这样的一个问题,有些.zip压缩包在Windows下直接打开是空的,但是通过一些第三方的压缩软件打开(比如7zip等),则是完全正常的。

通过一番调研和实验,我们发现,对于.zip这样如此常见的文件,在它数十年的发展历程中除了经历过前苏联的阶梯,伊拉克战争,.com的泡沫,次贷危机,互联网的繁荣与新冠疫情之外,自身的标准和实现也有过很多的变化,不同时代第三方软件也各自以自己对当时标准的理解做了不同的实现,所以滚滚的历史洪流依然可以给生活在今天我们冲来看似相同实则实现方式各种各样的.zip文件。而Windows自然是不屑支持这各种各样的实现的,所以也就让我们看到了这些空空如也的压缩包。

如前所述导致Windows下打开为空.zip包的原因并不唯一,下面列举一下我们在调研中发现的两种。

以/开头的路径

在zip的标准中,/是不可以作为路径的开头的,但是这并不意味着我们不能把/作为路径的前缀写到.zip文件中。如果文件路径是以/开头的,那么在Windows中打开这个.zip文件时,就无法显示这个路径。

我们可以通过下面的方式,生成一个路径以/开头的.zip文件

import zipfile

with zipfile.ZipFile('slash_prefix.zip', 'w') as zip_handle:
    zip_handle.writestr('/test.txt', b'')

注意,即使使用7zip打开这个文件,7zip会认为这个文件的路径是一个以空的目录。

文件路径中的特殊字符

如果.zip包,文件路径中包含中文等CJK字符,可以通过UTF-8对这些文件路径编码,而以UTF-8编码则需要通过flag bits中的第11位设置为1来声明。

但是一些软件还是会生成一些.zip包,其中的一些文件没有对flag bits进行合适的设置,但是文件路径中依然包含中文字符等。这样就会导致Windows在打开.zip包时,把文件名解析成乱码,而如果这些乱码包含一些特殊字符,就会进一步导致Windows不能显示这些路径,从而导致空.zip包的出现。

我们可以通过如下的例子,以这种方式生成一个在Windows打开为空的文件:

import zipfile

def _encodeFilenameFlags(self):
    return self.filename, self.flag_bits
zipfile.ZipInfo._encodeFilenameFlags = _encodeFilenameFlags

zip_handle = zipfile.ZipFile('encoding.zip', 'w')
info = zipfile.ZipInfo()
info.flag_bits = 0
info.filename = '包.txt'.encode('utf-8')
zip_handle.writestr(info, b'')
zip_handle.close()

可以看到,其实上面的代码生成的文件中,主要就是这个“包”字对应的编码造成了空文件夹的展示。

文件转换

对于存在上述的问题的文件,解决方法实际上也就是针对各自的文件进行转换,把转换好的文件重新存入一个新的zip包就可以了。一些zip包修复工具,实际上也是采取类似的方法来处理的。

比如,我们可以通过如下的Python函数对文件进行转换,就可以在Windows中正常打开了:

import zipfile

def convert(filename, new_filename):
    f = zipfile.ZipFile(filename)
    nf = zipfile.ZipFile(new_filename, mode='w')
    for zip_info in f.infolist():
        if not zip_info.flag_bits & 0x800:
            filename = zip_info.filename.encode('cp437').decode('utf-8')
        else:
            filename = zip_info.filename
        content = f.read(zip_info.filename)
        new_info = zipfile.ZipInfo()
        new_info.filename = filename.lstrip('/')
        new_info.date_time = zip_info.date_time
        new_info.flag_bits = zip_info.flag_bits | 0x800 
        new_info.extra = zip_info.extra
        new_info.internal_attr = zip_info.internal_attr
        new_info.external_attr = zip_info.external_attr
        new_info.file_size = len(content)
        nf.writestr(new_info, content)
    f.close()
    nf.close()
  • 7
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值