【python自动化办公(5)】zipfile模块解压中文文件出现乱码的问题(补充:代码实现带有中文文件的解压)

问题

python中的zipfile模块用来解压缩ZIP文件非常方便,但是如果ZIP文件的子文件的文件名里含有中文的话,解压出出来的文件的文件名却是乱码!虽然视频上讲过在读时通过编码形式解决,视频里只给了一行代码进行解码,但是在解压时如何进行解码呢?而且为什么这一行代码可以实现解码呢?

通过查看zipfile的源码后,发现了问题的根源:

if zinfo.flag_bits & 0x800:
    # UTF-8 filename
    fname_str = fname.decode("utf-8")
else:
    fname_str = fname.decode("cp437")

该段代码的意思就是:编码不能被正确识别为utf-8的时候,会被是被识别并decode为cp437编码,如果原来是gbk编码的话就会变成乱码。因此就有了视频里面的那一行代码

file_name = file_name.encode('cp437').decode('gbk')

对于解压后乱码的情况,可以先将压缩包里面的文件全部提取出来,然后进行文件重命名即可,代码如下

import os
import zipfile
import shutil

filePath = "C:\\Users\\86177\\Desktop\\这是一个压缩包.zip"
#filePath是压缩包文件位置
with zipfile.ZipFile(filePath, 'r') as zipobj:
	for file in zipobj.namelist():
	    filename = file.encode('cp437').decode('gbk')#先使用cp437编码,然后再使用gbk解码
	    #print(filename)
	    zipobj.extract(file,"C:\\Users\\86177\\Desktop")#解压缩ZIP文件,需要制定解压的位置
	    os.chdir("C:\\Users\\86177\\Desktop")  #回到解压后的文件路径
	    os.rename(file,filename) #重命名

–> 输出结果为:
在这里插入图片描述
这时候发现还多出来一个文件夹,而且里面只有放置文件的空文件夹,因此应该在解压完成后这个空文件夹也对应删除的,那么就要进行文件夹的删除

删除文件夹

两个问题:第一是如何删除文件夹?第二个是怎么找到这个乱码的文件夹呢?

删除

删除文件使用os.remove(文件名),这个由于很好记,所以经常被误用,只能删除文件,如果对象是文件夹时,执行这条语句就会报错

删除文件夹时使用shutil.rmtree(要删除的文件夹),需要提前导入shutil模块(import shutil)

os.remaoe("file1.txt")
shutil.rmtree('这是一个新建的文件夹')

乱码文件夹的选择

zipobj.namelist()实例中包含了全部的文件(路径),可以通过输出查看这个列表里面的内容(为了确认对应的乱码文件,这时候将上面代码注释的print(filename)代码显示出来),全部代码如下

import os
import zipfile
import shutil

filePath = "C:\\Users\\86177\\Desktop\\这是一个压缩包.zip"
#filePath是压缩包文件位置
with zipfile.ZipFile(filePath, 'r') as zipobj:
	for file in zipobj.namelist():
	    filename = file.encode('cp437').decode('gbk')#先使用cp437编码,然后再使用gbk解码
	    print(filename)
	    zipobj.extract(file,"C:\\Users\\86177\\Desktop")#解压缩ZIP文件,需要制定解压的位置
	    os.chdir("C:\\Users\\86177\\Desktop")  #回到解压后的文件路径
	    os.rename(file,filename) #重命名
print(zipobj.namelist())

–> 输出结果为:
在这里插入图片描述
由此可以看出列表中的第一个元素就是解压后乱码文件夹的名称,只不过是多了一个路径符号,这时候只需要进行一下字符串索引就可以获得目标字符。输出的目标乱码文件夹名称如下

print(zipobj.namelist()[0][:-1])

–> 输出结果为:╒Γ╩╟╥╗╕÷╤╣╦⌡░ⁿ (和上面截图生成的乱码文件夹字符一致)

至此删除文件夹的工作就完成了,也就代表这这个工作完成了,全部代码如下
import os
import zipfile
import shutil

filePath = "C:\\Users\\86177\\Desktop\\这是一个压缩包.zip"
with zipfile.ZipFile(filePath, 'r') as zipobj:
	for file in zipobj.namelist():
	    filename = file.encode('cp437').decode('gbk')
	    #print(filename)
	    zipobj.extract(file,"C:\\Users\\86177\\Desktop")
	    os.chdir("C:\\Users\\86177\\Desktop") 
	    os.rename(file,filename)#重命名文件

shutil.rmtree(zipobj.namelist()[0][:-1])

代码优化

在写上述代码的时候,有一个地方特别突兀就是存在着很多的路径字符,这些地方应该进行优化,先把优化代码写在下面

解压文件在同一路径下

import os
import zipfile
import shutil

os.chdir("D:\\python_major\\auto_office5_patch")

filePath = "这是一个压缩包.zip"
with zipfile.ZipFile(filePath, 'r') as zipobj:
	for file in zipobj.namelist():
	    filename = file.encode('cp437').decode('gbk')
	    zipobj.extract(file)
	    os.rename(file,filename)
    
shutil.rmtree(zipobj.namelist()[0][:-1])

运行结果是在D盘下的一个文件夹进行解压的(为了确认程序可以解压在不同路径下的压缩包),这里在最开始直接设置了代码程序运行的环境路径,就省了很多路径配置的问题,而且当解压文件和压缩包是同一个路径下的时候for循环中的倒数第二段代码可以省略,如果要解压到不同的路径,就需要按照下面的代码执行

解压文件在不同路径下

import os
import zipfile
import shutil

os.chdir("D:\\python_major\\auto_office5_patch")

filePath = "这是一个压缩包.zip"
with zipfile.ZipFile(filePath, 'r') as zipobj:
	for file in zipobj.namelist():
	    filename = file.encode('cp437').decode('gbk')
	    zipobj.extract(file,"D:\\model_2") #这里需要添加指定的解压路径
	    os.chdir("D:\\model_2") #这里将路径修改为解压文件所在路径
	    os.rename(file,filename)
    
shutil.rmtree(zipobj.namelist()[0][:-1])

建议:在涉及到文件(文件夹、压缩包、word、excel、ppt、txt等)的代码程序运行时候,尽量在导入os库后,添加一下程序的运行路径,这样会减少很多的代码工作量,而且代码运行过程中的文件都是会保存在设置的这个运行路径下,不会产生程序运行结束之后找不到文件的现象,良好的写代码习惯可以更加高效

发布了37 篇原创文章 · 获赞 10 · 访问量 4629

猜你喜欢

转载自blog.csdn.net/lys_828/article/details/104139379
今日推荐