目录
压缩包解压缩工具:Python小工具:压缩包解压缩工具
1. 常见的压缩包类型
1.1 TAR(.tar)
TAR(Tape Archive)是一种归档文件格式,主要用于将多个文件合并为一个文件,但本身不进行压缩。常用于Unix/Linux系统,保留文件权限、目录结构等元数据。归档后的文件体积与原始文件总和相同,需配合其他工具(如gzip、bzip2)进行压缩。
1.2 GZ(.gz)
GZ是GNU Zip(gzip)压缩工具生成的单文件压缩格式,仅压缩单个文件,不保留目录结构。通常与tar结合使用(如.tar.gz)。压缩率适中,速度快,广泛用于日志文件、网页资源等。
1.3 TAR.GZ(.tar.gz 或 .tgz)
TAR.GZ是先用tar归档多个文件,再用gzip压缩的复合格式。结合了tar的归档能力和gzip的压缩功能,适合压缩目录或文件组。Linux中常见软件发布格式,解压需分两步(或直接使用tar -xzf命令)。
1.4 ZIP(.zip)
ZIP是跨平台的归档压缩格式,支持多文件压缩和目录结构,内置压缩算法(如DEFLATE)。Windows系统原生支持,兼容性强,但压缩率通常低于TAR.GZ或TAR.BZ2。
1.5 TAR.BZ2(.tar.bz2 或 .tbz2)
使用tar归档后,用bzip2算法压缩。相比gzip,bzip2压缩率更高,但速度较慢。适用于需要高压缩率的场景,如大型数据集分发。
1.6 7Z(.7z)
7Z是7-Zip工具的高压缩率格式,支持多种算法(如LZMA)。压缩率优于ZIP和GZ,但解压需专用工具。适合需要极致压缩的场景。
1.7 RAR(.rar)
RAR是WinRAR的专有格式,支持分卷压缩和密码保护。压缩率较高,但需商业授权,Linux需第三方工具支持。
2. Python脚本实现文件压缩
使用python编写实现文件(夹)压缩工具,支持各种常见的压缩包类型,包括: .tar.gz、.tar、.gz、.zip、.tar.bz2、.7z、.rar 格式
源码如下:
import os
import tkinter as tk
from tkinter import filedialog, ttk, messagebox
import zipfile
import tarfile
import gzip
import threading
from datetime import datetime
import subprocess
class MultiFileCompressor:
def __init__(self, root):
self.root = root
self.root.title("多文件压缩工具")
self.root.geometry("650x650") # 增加高度以确保按钮可见
self.root.resizable(False, False)
# 设置样式
self.style = ttk.Style()
self.style.configure("TButton", padding=6, relief="flat", background="#ccc")
self.style.configure("Title.TLabel", font=("Arial", 14, "bold"))
self.style.configure("Header.TLabel", font=("Arial", 10, "bold"))
# 初始化变量
self.files_to_compress = []
self.compression_format = tk.StringVar(value="zip")
self.output_path = tk.StringVar()
self.archive_name = tk.StringVar(value=f"archive_{datetime.now().strftime('%Y%m%d_%H%M%S')}")
self.compression_level = tk.IntVar(value=6) # 默认压缩级别
# 支持的压缩格式
self.supported_formats = [
("ZIP 格式", "zip"),
("TAR 格式", "tar"),
("GZIP 格式", "gz"),
("TAR.GZ 格式", "tar.gz"),
("TAR.BZ2 格式", "tar.bz2"),
("7Z 格式", "7z"),
("RAR 格式", "rar")
]
# 创建界面
self.create_widgets()
def create_widgets(self):
# 主框架
main_frame = ttk.Frame(self.root)
main_frame.pack(fill="both", expand=True, padx=10, pady=10)
# 标题
title_label = ttk.Label(main_frame, text="多文件压缩工具", style="Title.TLabel")
title_label.pack(pady=10)
# 文件选择区域
file_frame = ttk.LabelFrame(main_frame, text="选择要压缩的文件")
file_frame.pack(fill="x", pady=5)
# 文件列表
self.file_listbox = tk.Listbox(file_frame, height=8, selectmode=tk.EXTENDED)
self.file_listbox.pack(fill="x", padx=5, pady=5)
# 文件操作按钮
button_frame = ttk.Frame(file_frame)
button_frame.pack(fill="x", padx=5, pady=5)
add_file_btn = ttk.Button(button_frame, text="添加文件", command=self.add_files)
add_file_btn.pack(side="left", padx=5)
add_folder_btn = ttk.Button(button_frame, text="添加文件夹", command=self.add_folder)
add_folder_btn.pack(side="left", padx=5)
remove_btn = ttk.Button(button_frame, text="移除选中", command=self.remove_selected)
remove_btn.pack(side="left", padx=5)
clear_btn = ttk.Button(button_frame, text="清空列表", command=self.clear_list)
clear_btn.pack(side="left", padx=5)
# 压缩选项区域
options_frame = ttk.LabelFrame(main_frame, text="压缩选项")
options_frame.pack(fill="x", pady=5)
# 压缩格式选择
format_frame = ttk.Frame(options_frame)
format_frame.pack(fill="x", padx=5, pady=5)
ttk.Label(format_frame, text="压缩格式:").pack(side="left")
# 创建格式选择下拉菜单
format_combo = ttk.Combobox(format_frame, textvariable=self.compression_format,
values=[fmt[1] for fmt in self.supported_formats],
state="readonly", width=10)
format_combo.pack(side="left", padx=10)
# 绑定格式变更事件
format_combo.bind("<<ComboboxSelected>>", self.on_format_change)
# 压缩级别(仅对zip有效)
self.level_frame = ttk.Frame(options_frame)
self.level_frame.pack(fill="x", padx=5, pady=5)
ttk.Label(self.level_frame, text="压缩级别 (0-9):").pack(side="left")
self.level_spinbox = ttk.Spinbox(self.level_frame, from_=0, to=9,
textvariable=self.compression_level,
width=5, state="readonly")
self.level_spinbox.pack(side="left", padx=10)
# 输出选项区域
output_frame = ttk.LabelFrame(main_frame, text="输出选项")
output_frame.pack(fill="x", pady=5)
# 压缩包名称
name_frame = ttk.Frame(output_frame)
name_frame.pack(fill="x", padx=5, pady=5)
ttk.Label(name_frame, text="压缩包名称:").pack(side="left")
name_entry = ttk.Entry(name_frame, textvariable=self.archive_name)
name_entry.pack(side="left", padx=10, fill="x", expand=True)
# 输出路径
path_frame = ttk.Frame(output_frame)
path_frame.pack(fill="x", padx=5, pady=5)
ttk.Label(path_frame, text="输出路径:").pack(side="left")
path_entry = ttk.Entry(path_frame, textvariable=self.output_path)
path_entry.pack(side="left", padx=10, fill="x", expand=True)
ttk.Button(path_frame, text="浏览", command=self.select_output_path).pack(side="left", padx=5)
# 状态标签
self.status_label = ttk.Label(main_frame, text="就绪", relief="sunken", anchor="w")
self.status_label.pack(fill="x", pady=5)
# 进度条
self.progress = ttk.Progressbar(main_frame, mode="indeterminate")
self.progress.pack(fill="x", pady=5)
# 压缩按钮 - 确保这个按钮在最底部
compress_btn = ttk.Button(main_frame, text="开始压缩", command=self.start_compression)
compress_btn.pack(pady=10)
def on_format_change(self, event):
# 根据选择的格式显示或隐藏压缩级别选项
fmt = self.compression_format.get()
if fmt in ["zip", "gz", "7z"]:
self.level_frame.pack(fill="x", padx=5, pady=5)
else:
self.level_frame.pack_forget()
def add_files(self):
files = filedialog.askopenfilenames(title="选择要压缩的文件")
if files:
for file in files:
if file not in self.files_to_compress:
self.files_to_compress.append(file)
self.file_listbox.insert(tk.END, os.path.basename(file))
self.update_status(f"已添加 {len(files)} 个文件")
def add_folder(self):
folder = filedialog.askdirectory(title="选择要压缩的文件夹")
if folder:
if folder not in self.files_to_compress:
self.files_to_compress.append(folder)
self.file_listbox.insert(tk.END, f"[文件夹] {os.path.basename(folder)}")
self.update_status(f"已添加文件夹: {os.path.basename(folder)}")
def remove_selected(self):
selected_indices = self.file_listbox.curselection()
for index in selected_indices[::-1]: # 从后往前删除,避免索引变化
self.file_listbox.delete(index)
self.files_to_compress.pop(index)
self.update_status(f"已移除 {len(selected_indices)} 个项目")
def clear_list(self):
count = len(self.files_to_compress)
self.file_listbox.delete(0, tk.END)
self.files_to_compress.clear()
self.update_status(f"已清空 {count} 个项目")
def select_output_path(self):
path = filedialog.askdirectory(title="选择输出路径")
if path:
self.output_path.set(path)
self.update_status(f"输出路径: {path}")
def update_status(self, message):
self.status_label.config(text=message)
def start_compression(self):
if not self.files_to_compress:
messagebox.showerror("错误", "请至少选择一个文件或文件夹进行压缩")
return
if not self.output_path.get():
messagebox.showerror("错误", "请选择输出路径")
return
# 检查7z和rar格式的支持
fmt = self.compression_format.get()
if fmt == "7z" and not self.check_7z_support():
messagebox.showerror("错误", "7z压缩需要安装7-Zip软件并添加到系统PATH中")
return
if fmt == "rar" and not self.check_rar_support():
messagebox.showerror("错误", "RAR压缩需要安装WinRAR软件并添加到系统PATH中")
return
# 禁用界面并启动进度条
self.set_ui_state(False)
self.progress.start(10)
# 在新线程中执行压缩操作
thread = threading.Thread(target=self.compress_files)
thread.daemon = True
thread.start()
def check_7z_support(self):
"""检查系统是否支持7z压缩"""
try:
result = subprocess.run(["7z", "--help"],
capture_output=True, text=True, timeout=2)
return result.returncode == 0
except (subprocess.TimeoutExpired, FileNotFoundError):
return False
def check_rar_support(self):
"""检查系统是否支持RAR压缩"""
try:
result = subprocess.run(["rar", "--help"],
capture_output=True, text=True, timeout=2)
return result.returncode == 0
except (subprocess.TimeoutExpired, FileNotFoundError):
# 在Windows上也可能是WinRAR的路径不同
try:
result = subprocess.run(["winrar", "/?"],
capture_output=True, text=True, timeout=2)
return result.returncode == 0
except (subprocess.TimeoutExpired, FileNotFoundError):
return False
def compress_files(self):
try:
fmt = self.compression_format.get()
level = self.compression_level.get()
output_file = os.path.join(
self.output_path.get(),
f"{self.archive_name.get()}.{fmt}"
)
self.update_status(f"正在压缩到 {fmt} 格式...")
if fmt == "zip":
self.create_zip_archive(output_file, level)
elif fmt == "tar":
self.create_tar_archive(output_file)
elif fmt == "gz":
self.create_gz_archive(output_file, level)
elif fmt == "tar.gz":
self.create_tar_gz_archive(output_file)
elif fmt == "tar.bz2":
self.create_tar_bz2_archive(output_file)
elif fmt == "7z":
self.create_7z_archive(output_file, level)
elif fmt == "rar":
self.create_rar_archive(output_file)
# 完成后恢复界面状态
self.root.after(0, self.compression_complete, output_file)
except Exception as e:
self.root.after(0, self.compression_error, str(e))
def create_zip_archive(self, output_file, level):
with zipfile.ZipFile(
output_file, 'w',
compression=zipfile.ZIP_DEFLATED,
compresslevel=level
) as zipf:
for item in self.files_to_compress:
if os.path.isfile(item):
zipf.write(item, os.path.basename(item))
elif os.path.isdir(item):
for root, _, files in os.walk(item):
for file in files:
file_path = os.path.join(root, file)
arcname = os.path.relpath(file_path, os.path.dirname(item))
zipf.write(file_path, arcname)
def create_tar_archive(self, output_file):
with tarfile.open(output_file, "w") as tar:
for item in self.files_to_compress:
if os.path.isfile(item):
tar.add(item, arcname=os.path.basename(item))
elif os.path.isdir(item):
tar.add(item, arcname=os.path.basename(item))
def create_gz_archive(self, output_file, level):
# GZ格式只能压缩单个文件
if len(self.files_to_compress) > 1:
raise Exception("GZ格式只能压缩单个文件")
item = self.files_to_compress[0]
if os.path.isdir(item):
raise Exception("GZ格式不能压缩文件夹")
with open(item, 'rb') as f_in:
with gzip.open(output_file, 'wb', compresslevel=level) as f_out:
f_out.writelines(f_in)
def create_tar_gz_archive(self, output_file):
with tarfile.open(output_file, "w:gz") as tar:
for item in self.files_to_compress:
if os.path.isfile(item):
tar.add(item, arcname=os.path.basename(item))
elif os.path.isdir(item):
tar.add(item, arcname=os.path.basename(item))
def create_tar_bz2_archive(self, output_file):
with tarfile.open(output_file, "w:bz2") as tar:
for item in self.files_to_compress:
if os.path.isfile(item):
tar.add(item, arcname=os.path.basename(item))
elif os.path.isdir(item):
tar.add(item, arcname=os.path.basename(item))
def create_7z_archive(self, output_file, level):
# 构建7z命令
cmd = ["7z", "a", "-t7z", f"-mx={level}", output_file]
cmd.extend(self.files_to_compress)
# 执行7z命令
result = subprocess.run(cmd, capture_output=True, text=True)
if result.returncode != 0:
raise Exception(f"7z压缩失败: {result.stderr}")
def create_rar_archive(self, output_file):
# 尝试使用rar命令
try:
cmd = ["rar", "a", output_file]
cmd.extend(self.files_to_compress)
result = subprocess.run(cmd, capture_output=True, text=True)
if result.returncode == 0:
return
except FileNotFoundError:
pass
# 尝试使用winrar命令(Windows)
try:
cmd = ["winrar", "a", output_file]
cmd.extend(self.files_to_compress)
result = subprocess.run(cmd, capture_output=True, text=True)
if result.returncode != 0:
raise Exception(f"RAR压缩失败: {result.stderr}")
except FileNotFoundError:
raise Exception("未找到RAR压缩工具,请确保已安装WinRAR或RAR命令行工具")
def compression_complete(self, output_file):
self.progress.stop()
self.set_ui_state(True)
self.update_status("压缩完成")
messagebox.showinfo("完成", f"压缩完成!\n文件已保存至: {output_file}")
def compression_error(self, error_msg):
self.progress.stop()
self.set_ui_state(True)
self.update_status("压缩失败")
messagebox.showerror("错误", f"压缩过程中发生错误:\n{error_msg}")
def set_ui_state(self, enabled):
# 查找所有按钮并设置状态
for widget in self.root.winfo_children():
if isinstance(widget, (ttk.Button, ttk.Combobox, ttk.Spinbox)):
widget.state(["!disabled" if enabled else "disabled"])
# 设置文件列表框状态
self.file_listbox.config(state=tk.NORMAL if enabled else tk.DISABLED)
if __name__ == "__main__":
root = tk.Tk()
app = MultiFileCompressor(root)
root.mainloop()

被折叠的 条评论
为什么被折叠?



