Python 解壓縮Zip和Rar文件到指定目錄


#__author__ = 'Joker'
# -*- coding:utf-8 -*-
import urllib
import os
import os.path
import zipfile
from zipfile import *
import sys
reload(sys)
sys.setdefaultencoding('gbk')

rootdir = "F:/50_GIS/1000_Tools" # 指明被遍歷的文件夾
zipdir = "F:/000_Terrain/zipdir" # 存儲解壓縮后的文件夾

#Zip文件處理類
class ZFile(object):
def __init__(self, filename, mode='r', basedir=''):
self.filename = filename
self.mode = mode
if self.mode in ('w', 'a'):
self.zfile = zipfile.ZipFile(filename, self.mode, compression=zipfile.ZIP_DEFLATED)
else:
self.zfile = zipfile.ZipFile(filename, self.mode)
self.basedir = basedir
if not self.basedir:
self.basedir = os.path.dirname(filename)

def addfile(self, path, arcname=None):
path = path.replace('//', '/')
if not arcname:
if path.startswith(self.basedir):
arcname = path[len(self.basedir):]
else:
arcname = ''
self.zfile.write(path, arcname)

def addfiles(self, paths):
for path in paths:
if isinstance(path, tuple):
self.addfile(*path)
else:
self.addfile(path)

def close(self):
self.zfile.close()

def extract_to(self, path):
for p in self.zfile.namelist():
self.extract(p, path)

def extract(self, filename, path):
if not filename.endswith('/'):
f = os.path.join(path, filename)
dir = os.path.dirname(f)
if not os.path.exists(dir):
os.makedirs(dir)
file(f, 'wb').write(self.zfile.read(filename))

#創建Zip文件
def createZip(zfile, files):
z = ZFile(zfile, 'w')
z.addfiles(files)
z.close()

#解壓縮Zip到指定文件夾
def extractZip(zfile, path):
z = ZFile(zfile)
z.extract_to(path)
z.close()

#解壓縮rar到指定文件夾
def extractRar(zfile, path):
rar_command1 = "WinRAR.exe x -ibck %s %s" % (zfile, path)
rar_command2 = r'"C:\WinRAR.exe" x -ibck %s %s' % (zfile, path)
if os.system(rar_command1) == 0:
print "Path OK."
else:

if os.system(rar_command2) != 0:
print "Error."
else:
print "Exe OK"

#獲得文件名和后綴
def GetFileNameAndExt(filename):
(filepath,tempfilename) = os.path.split(filename);
(shotname,extension) = os.path.splitext(tempfilename);
return shotname,extension

#定義文件處理數量-全局變量
fileCount = 0

#遞歸獲得rar文件集合
def getFiles(filepath):
#遍歷filepath下所有文件,包括子目錄
files = os.listdir(filepath)
for fi in files:
fi_d = os.path.join(filepath,fi)
if os.path.isdir(fi_d):
getFiles(fi_d)
else:
global fileCount
global zipdir
fileCount = fileCount + 1
# print fileCount
fileName = os.path.join(filepath,fi_d)
filenamenoext = GetFileNameAndExt(fileName)[0]
fileext = GetFileNameAndExt(fileName)[1]
# 如果要保存到同一個文件夾,將文件名設為空
filenamenoext = ""
zipdirdest = zipdir + "/" + filenamenoext + "/"
if fileext in ['.zip','.rar']:
if not os.path.isdir(zipdirdest):
os.mkdir(zipdirdest)
if fileext == ".zip" :#
print str(fileCount) + " -- " + fileName
# unzip(fileName,zipdirdest)
extractZip(fileName,zipdirdest)
elif fileext == ".rar":
print str(fileCount) + " -- " + fileName
extractRar(fileName, zipdirdest)

#遞歸遍歷“rootdir”目錄下的指定后綴的文件列表
getFiles(rootdir)

Zip處理:http://www.cnblogs.com/qq78292959/archive/2013/03/27/2985310.html
文件處理參考:http://www.cnblogs.com/txw1958/archive/2012/03/08/2385540.html


讀取Zip文件

隨便一個zip文件,我這里用了bb.zip,就是一個文件夾bb,里面有個文件aa.txt。

import zipfile # 默認模式r,讀 azip = zipfile.ZipFile('bb.zip') # ['bb/', 'bb/aa.txt'] # 返回所有文件夾和文件 print(azip.namelist()) # # 返回該zip的文件名 print(azip.filename) # 壓縮文件里bb文件夾下的aa.txt azip_info = azip.getinfo('bb/aa.txt') # 原來文件大小 print(azip_info.file_size) # 壓縮后大小 print(azip_info.compress_size) # 這樣可以求得壓縮率,保留小數點后兩位 print('壓縮率為{:.2f}'.format(azip_info.file_size/azip_info.compress_size)) 

可以看到打開方式並不是想象中的open,而是ZipFile。用namelist()可以返回里面所有的文件夾和文件路徑。getinfo可以獲得某路徑下文件的信息,如上。

還能直接讀取壓縮包里文件的內容,下面兩種方法得到的結果是一樣的。需要注意的是,讀取出來的數據好像是字節形式的,解碼成utf-8就好

# 可以直接讀取里面的內容, 不過貌似是字節形式.需要解碼回utf-8.參數也可以傳ZiInfo, 如b a = azip.read('bb/cc.txt').decode('utf-8') print(a) # 打開文件再讀取,好像比上面麻煩 b = azip.open(azip_info) print(b.read().decode('utf-8')) azip.close()

用完資源后記得主動close。

解壓Zip

最為關鍵的功能,一句搞定。默認解壓在當前工作目錄,可以指定解壓目錄。

azip.extractall()

新建Zip文件

不僅能讀還能寫。新建壓縮包的時候,可以選擇壓縮算法,比如DEFLATED和LZMA

# 新建壓縮包,放文件進去,若壓縮包已經存在,將覆蓋。可選擇用a模式,追加 azip = zipfile.ZipFile('bb.zip', 'w') # 必須保證路徑存在,將bb件夾(及其下aa.txt)添加到壓縮包,壓縮算法LZMA azip.write('D:/bb/aa.txt', compress_type=zipfile.ZIP_LZMA) # 寫入一個新文件到壓縮包中,data是該文件的具體內容,可以是str或者是byte。 # 這里是新建一個bb文件夾,其下再新建一個cc.txt,將hello world寫入到文本中 azip.writestr('bb/cc.txt', data='Hello World', compress_type=zipfile.ZIP_DEFLATED) # 關閉資源 azip.close()

上面有兩個方法比較類似,注意區分。

  • write指的是將已經存在的文件復制到壓縮包,包括路徑中的所有文件夾河其下的文件。
  • writestr是直接在壓縮包里新建文件夾和文件,data參數是往該文件中寫入的內容。

最終壓縮包里會被添加bb文件夾,其下有aa.txtcc.txt

將整個文件夾添加到壓縮包中

如果我們這樣寫,想象着能添加bb文件夾下所有內容到壓縮包中,那就不對了。這樣添加,只會把bb文件夾復制過去,也僅僅如此,里面的文件不會添加到壓縮包。最后得到的只是一個空文件夾。

azip.write(r'D:/bb', compress_type=zipfile.ZIP_LZMA)

那怎么辦呢?只好遞歸查找添加了,os.walk剛好可以幫助我們。

for current_path, subfolders, filesname in os.walk(r'D:\bb'): print(current_path, subfolders, filesname) # filesname是一個列表,我們需要里面的每個文件名和當前路徑組合 for file in filesname: # 將當前路徑與當前路徑下的文件名組合,就是當前文件的絕對路徑 azip.write(os.path.join(current_path, file)) # 關閉資源 azip.close() 

正確選用變量,元組中第一個是當前路徑,而第三個是當前路徑下的文件,兩者一組合剛好就是文件的絕對路徑。

這樣就可以實現添加整個文件夾添加到壓縮包了。而且是這些路徑下所有的文件夾和其下的文件全部添加。也就是說,保留了原文件夾的結構層次。

shutil添加壓縮包和解壓縮

shuitl模塊有個函數,可以方便地添加整個整個文件夾到壓縮包。

# 第一個參數是歸檔文件名稱,第二個參數是指定的格式,不僅是支持zip,第三個參數是要壓縮文件/文件夾的路徑 shutil.make_archive('archive_name', 'zip', r'F:\IDE Setting') # shutil.get_archive_formats() 可以查看支持的格式

當然也可以解壓縮,可指定解壓目錄,否則默認解壓到當前工作目錄

shutil.unpack_archive(r'D:\bb.zip') # shutil.get_unpack_formats() 可以查看支持的格式


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM