吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 13123|回复: 328
收起左侧

[Windows] 文件复制工具v1.2-更新

    [复制链接]
william0712 发表于 2024-9-13 16:02
本帖最后由 william0712 于 2024-9-29 11:16 编辑
           昨天复制多个生产文件和灰度文件的时候,才发现当出现多个文件分别复制去多个目录的时候,WIN处理不来就越来越慢,大家都挤同一条道路上去了卡着动不起来了,

大概这位仁兄也是在找它吧;吾爱求助帖


所以萌生了写这个工具的念头,工具的作用只有一个,就是按照你所选择的文件想复制去哪个目标路径就去哪个,先以列表的形式展现出来,最后再按顺序执行,运行截图如下

启动之后,添加你想要复制的文件或文件夹(要分开选择,没办法python决定的),然后右边选择你要把文件放去哪个目标路径,然后点添加任务

进行中.jpg


所有任务添加完就可以开始执行了,已完成的任务会变绿,如下图。


已加入多线程处理和异步复制解决卡机问题,缓冲区从1M调到了8M,也不是越大越好,得看你的机器内存和硬盘效率,后期可能会加入自设缓冲区大小的功能吧,还有什么问题也欢迎大家提出来。

哈勃查毒https://habo.qq.com/file/showdetail?pk=ADYGYl1pB2EIMFs6U2oHYA%3D%3D
还是那句,火绒查毒无问题,python打包的,360安全卫士可能会报毒,就算代码里只有一条print "Hello world!",它也报毒,无语了,自行选择,360真的是越来越垃圾了,下载链接放123盘了,支持浏览器直下。前50回复有币,给大家伙回回血吧。
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
09.21.更新:
1.线程间同步机制:使用锁来同步任务队列的操作。
2.异常处理:在文件操作中增加异常捕获。
3.线程安全处理:使用锁来保护任务队列。
4.进度条优化。
5.文件覆盖可选。
6.加入任务暂停机制;
7.加入任务列表的保存与读取;
8.加入右键单独删除某个任务。

0921.jpg

下载链接
https://www.123pan.com/s/EG5A-GM0AH
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
代码如下
[Python] 纯文本查看 复制代码
import tkinter as tkfrom tkinter import filedialog, messagebox, ttk
import shutil
import os
import threading


class FileCopyTool:
    def __init__(self, master):
        self.master = master
        master.title("文件复制工具 by.KOG丛林")

        self.copy_tasks = []
        self.current_task_index = 0

        # 左上区域:选择文件/文件夹
        left_frame = tk.Frame(master)
        left_frame.grid(row=0, column=0, sticky='nsew')

        source_label = tk.Label(left_frame, text="源文件/文件夹:")
        source_label.pack(pady=(10, 0))

        self.source_entry = tk.Entry(left_frame, width=50)
        self.source_entry.pack(pady=(0, 10))

        browse_files_button = tk.Button(left_frame, text="             选择文件             ", command=self.browse_files)
        browse_files_button.pack(side=tk.LEFT, padx=(0, 5), pady=(5, 10))

        browse_dirs_button = tk.Button(left_frame, text="             选择文件夹             ", command=self.browse_directories)
        browse_dirs_button.pack(side=tk.LEFT, padx=(5, 0), pady=(5, 10))

        # 右上区域:目标路径
        right_frame = tk.Frame(master)
        right_frame.grid(row=0, column=1, sticky='nsew')

        destination_label = tk.Label(right_frame, text="目标目录:")
        destination_label.pack(pady=(10, 0))

        self.destination_entry = tk.Entry(right_frame, width=50)
        self.destination_entry.pack(pady=(0, 10))

        browse_destination_button = tk.Button(right_frame, text="         浏览         ", command=self.browse_destination)
        browse_destination_button.pack(pady=(5, 10))

        # 下半区域:任务列表
        bottom_frame = tk.Frame(master)
        bottom_frame.grid(row=1, column=0, columnspan=2, sticky='nsew')

        self.task_listbox = tk.Listbox(bottom_frame, selectmode=tk.MULTIPLE)
        self.task_listbox.pack(side=tk.TOP, fill=tk.BOTH, expand=True, padx=10, pady=10)

        self.clear_list_button = tk.Button(bottom_frame, text="清空列表", command=self.clear_list)
        self.clear_list_button.pack(side=tk.LEFT, pady=(0, 10))

        self.progress_bar = ttk.Progressbar(bottom_frame, orient="horizontal", length=200, mode="determinate")
        self.progress_bar.pack(side=tk.TOP, padx=10, pady=(0, 10), fill=tk.X)

        self.add_task_button = tk.Button(bottom_frame, text="                          添加任务                       ", command=self.add_task)
        self.add_task_button.pack(side=tk.LEFT, pady=(0, 10))

        self.execute_button = tk.Button(bottom_frame, text="                            开始执行                                    ", command=self.execute_tasks)
        self.execute_button.pack(side=tk.RIGHT, pady=(0, 10))

        # 设置网格权重,使任务列表框可扩展
        master.grid_columnconfigure(0, weight=1)
        master.grid_columnconfigure(1, weight=1)
        master.grid_rowconfigure(1, weight=1)

    def browse_files(self):
        sources = filedialog.askopenfilenames(initialdir="/", title="选择文件",
                                              filetypes=(("all files", "*.*"), ("text files", "*.txt")))
        if sources:
            self.source_entry.delete(0, tk.END)
            self.source_entry.insert(0, ', '.join(sources))

    def browse_directories(self):
        dirs = filedialog.askdirectory(initialdir="/", title="选择文件夹")
        if dirs:
            self.source_entry.delete(0, tk.END)
            self.source_entry.insert(0, dirs)

    def browse_destination(self):
        destination_dir = filedialog.askdirectory()
        self.destination_entry.delete(0, tk.END)
        self.destination_entry.insert(0, destination_dir)

    def add_task(self):
        sources = self.source_entry.get().split(', ')
        destination = self.destination_entry.get()
        if sources and destination:
            for source in sources:
                source = source.strip()
                if os.path.exists(source):
                    self.copy_tasks.append((source, destination))
                    self.task_listbox.insert(tk.END, f"从 {source} 复制到 {destination}")
            self.clear_entries()

    def clear_list(self):
        self.task_listbox.delete(0, tk.END)

    def clear_entries(self):
        self.source_entry.delete(0, tk.END)
        self.destination_entry.delete(0, tk.END)

    def update_progress(self, value):
        self.progress_bar['value'] = value
        self.master.update_idletasks()

    def copy_file_with_progress(self, source, destination):
        BUFFER_SIZE = 1024 * 1024 * 8  # 8 MB buffer size
        total_size = os.path.getsize(source)
        copied_size = 0
        with open(source, 'rb') as src, open(destination, 'wb') as dst:
            while True:
                buf = src.read(BUFFER_SIZE)  # Read 8MB at a time
                if not buf:
                    break
                dst.write(buf)
                copied_size += len(buf)
                progress = int((copied_size / total_size) * 100)
                self.update_progress(progress)

    def copy_folder_with_progress(self, source_folder, destination_folder):
        for root, dirs, files in os.walk(source_folder):
            relpath = os.path.relpath(root, source_folder)
            dest_path = os.path.join(destination_folder, relpath)
            os.makedirs(dest_path, exist_ok=True)
            for file in files:
                src_file = os.path.join(root, file)
                dest_file = os.path.join(dest_path, file)
                self.copy_file_with_progress(src_file, dest_file)

    def execute_tasks(self):
        self.current_task_index = 0
        self.master.update_idletasks()  # 更新进度条和任务状态

        def run_tasks():
            for index, task in enumerate(self.copy_tasks):
                source, destination = task
                if os.path.isfile(source):
                    destination_path = os.path.join(destination, os.path.basename(source))
                    self.copy_file_with_progress(source, destination_path)
                elif os.path.isdir(source):
                    destination_path = os.path.join(destination, os.path.basename(source))
                    self.copy_folder_with_progress(source, destination_path)
                self.task_listbox.itemconfig(index, {'bg': 'green'})
                self.update_progress(100)
                self.current_task_index += 1
                self.master.update_idletasks()
            messagebox.showinfo("完成", "所有任务已完成!")

        # 在新线程中执行任务
        thread = threading.Thread(target=run_tasks)
        thread.start()


if __name__ == "__main__":
    root = tk.Tk()
    root.grid_rowconfigure(1, weight=1)
    root.grid_columnconfigure(0, weight=1)
    root.grid_columnconfigure(1, weight=1)

    my_gui = FileCopyTool(root)
    root.mainloop()

免费评分

参与人数 50吾爱币 +48 热心值 +40 收起 理由
david003 + 1 + 1 谢谢@Thanks!
jdxjwz + 1 + 1 谢谢@Thanks!
anqi520510 + 1 + 1 谢谢@Thanks!
xiaojundeng + 1 + 1 谢谢@Thanks!
yzqgeorge + 1 + 1 谢谢@Thanks!
knn2011 + 1 用心讨论,共获提升!
qwedxs + 1 + 1 我很赞同!
woxobo + 1 + 1 谢谢@Thanks!
微凉小小 + 1 + 1 热心回复!
card628 + 1 热心回复!
wsldboy + 1 + 1 谢谢@Thanks!
yiqibufenli + 1 + 1 我很赞同!
h07799486 + 1 + 1 谢谢@Thanks!
zj_tj + 1 + 1 热心回复!
yxpp + 1 谢谢@Thanks!
laodeng + 1 + 1 大佬牛逼!
asas1010 + 1 + 1 谢谢@Thanks!
ngq0530 + 1 用心讨论,共获提升!
muzi337 + 1 + 1 感谢您的宝贵建议,我们会努力争取做得更好!
keruh123 + 1 + 1 谢谢@Thanks!
cyx94a + 1 + 1 我很赞同!
uyli + 1 <font style="vertical-align: inherit;"><font style=
jiaokeer + 1 + 1 谢谢@Thanks!
nakasou + 2 + 1 热心回复!
qiaoyong + 1 + 1 热心回复!
xyz66889 + 1 + 1 谢谢@Thanks!
pdcba + 1 + 1 谢谢@Thanks!
wang82530 + 1 + 1 鼓励转贴优秀软件安全工具和文档!
butklmrz + 1 谢谢@Thanks!
无尘浪子 + 1 谢谢@Thanks!
yaan + 1 + 1 热心回复!
Issacclark1 + 1 谢谢@Thanks!
wudavid33 + 1 + 1 热心回复!
Justdoz + 1 + 1 热心回复!
kewu200 + 1 + 1 我很赞同!
抱薪风雪雾 + 1 + 1 谢谢@Thanks!
wangccyy + 1 谢谢@Thanks!
loveyunye + 1 + 1 谢谢@Thanks!
联合会 + 1 + 1 热心回复!
dogox + 1 + 1 我很赞同!
搞点什么 + 1 + 1 谢谢@Thanks!
way824325223 + 1 谢谢@Thanks!
powehi + 1 + 1 谢谢@Thanks!
远方呢 + 1 谢谢@Thanks!
PoJ575 + 1 + 1 谢谢@Thanks!
wanfon + 1 + 1 热心回复!
yanglinman + 1 谢谢@Thanks!
hf007007 + 1 + 1 我很赞同!
windowxp03 + 1 + 1 谢谢@Thanks!
SuXiao + 1 我很赞同!

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

szx1 发表于 2024-9-15 11:08
代码功能分析
该代码是一个基于 Tkinter 框架的 GUI 工具,用于复制文件和文件夹。它的主要功能包括:

选择源文件或源文件夹:通过文件对话框选择源文件或文件夹,并将其路径显示在输入框中。
选择目标路径:通过对话框选择目标文件夹,将文件或文件夹复制到此路径。
添加任务:用户可以添加多个复制任务,每个任务包括一个源文件/文件夹和一个目标路径,并将这些任务显示在任务列表中。
任务执行:按下“开始执行”按钮后,程序会按顺序执行任务,将源文件/文件夹复制到目标路径。文件复制过程会显示进度条,且文件复制是通过新线程执行的,避免 GUI 界面卡死。
进度更新:文件复制的过程中,进度条会根据复制的百分比更新,同时任务完成后,会将列表中的对应项标记为绿色。
任务清理:可以清空任务列表。
代码潜在风险性分析
多线程问题:

该工具使用 threading.Thread 来避免主线程阻塞,然而没有使用线程锁等机制来防止线程并发问题。如果用户在执行任务时同时进行其他操作(如再次添加任务、清空列表等),可能导致线程安全问题。
异常处理缺失:

在文件复制过程中(如文件读写、文件夹遍历),如果出现文件不存在、权限问题或磁盘空间不足等异常情况,该代码没有做任何异常处理。这会导致程序崩溃或任务无法继续。
shutil.copy 函数其实可以更好地处理文件系统的复制,而手动读写文件部分没有考虑这些异常,比如无法写入目标文件时程序没有相应处理。
进度条更新问题:

进度条的更新逻辑可能会有问题,特别是在处理大文件夹时,文件夹的复制进度是基于每个文件的单独进度,整个文件夹复制完成后进度条才会显示为 100%。这可能导致用户在长时间复制过程中无法看到文件夹复制的总体进展。
UI 响应延迟:

尽管文件复制被放在子线程中进行,但在主线程中调用 update_idletasks 强制刷新 UI,可能会引起一些不必要的延迟。尤其是在处理大量小文件时,频繁更新进度可能导致性能问题。
目标路径覆盖风险:

代码在复制文件时没有检查目标路径是否已经存在同名文件,直接覆盖同名文件可能会造成数据丢失风险。文件复制工具通常需要提供一个覆盖、跳过或重命名的选项,以确保用户不会无意间覆盖重要文件。
任务队列并发问题:

在执行任务时,如果用户反复添加任务或者清空任务列表,可能会导致任务队列状态与 UI 不一致的情况,因为当前没有线程间的同步机制。
改进建议
增加异常处理:在文件操作部分加入 try-except 块,捕获文件读写、权限、磁盘问题等异常,确保程序不会因个别任务出错而崩溃,并在 GUI 中给予用户提示。

线程安全处理:使用 threading.Lock 或 queue.Queue 来管理任务队列,确保在任务执行时不会受到用户其他操作的干扰。

进度条优化:针对文件夹复制,提供基于文件夹整体大小的进度更新,而不是单个文件的进度,这样用户可以看到文件夹复制的总体进展。

文件覆盖提示:在复制文件时,检查目标目录中是否存在同名文件,并提示用户选择是否覆盖、跳过或重命名文件。

性能优化:考虑限制进度条的更新频率,减少 update_idletasks 的调用次数,尤其是在大量小文件复制的场景下,以提升性能。

通过以上的改进,工具将更加稳定、可靠,并且减少潜在的风险和用户数据丢失的可能性。
ShanYao047 发表于 2024-9-15 11:09
Bakura 发表于 2024-9-13 17:28
L379 发表于 2024-9-15 13:07
有个 fastcopy 软件复制很好用的
田田爱崽崽 发表于 2024-9-13 16:03

回帖奖励 +1 CB吾爱币

感谢大佬分享
我是谁啊 发表于 2024-9-13 16:03

回帖奖励 +1 CB吾爱币

感谢大佬分享
sunlu 发表于 2024-9-13 16:04

回帖奖励 +1 CB吾爱币


感谢分享
ttmusic 发表于 2024-9-13 16:07

回帖奖励 +1 CB吾爱币

感谢分享
7086pp 发表于 2024-9-13 16:08

回帖奖励 +1 CB吾爱币

感谢分享
Zrzy123456 发表于 2024-9-13 16:08

回帖奖励 +1 CB吾爱币

感谢大佬分享
802811 发表于 2024-9-13 16:09

回帖奖励 +1 CB吾爱币

感谢大佬撒币
隔壁小孩馋了 发表于 2024-9-13 16:09

回帖奖励 +1 CB吾爱币

这咋还给奖励了
wenping050 发表于 2024-9-13 16:09

回帖奖励 +1 CB吾爱币

后台复制。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-22 06:29

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表