You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何将控制台文件复制进度条与复制进程同步?

解决文件复制与进度条同步更新的问题

嘿,这个问题我之前也踩过坑!你现在的代码逻辑是先同步完成整个文件复制File.Copy是阻塞调用,会一直等到复制完全结束才往下执行),之后再模拟进度条动画,所以自然会出现“先空白复制,再跑进度条”的脱节情况。要让两者同步,我们需要自己实现带进度跟踪的文件复制逻辑,实时把复制进度传递给进度条。

下面是具体的修改方案:

核心思路

  • 放弃使用File.Copy,改用FileStream分块读写文件,这样能实时获取已复制的字节数
  • 计算已复制字节数占总文件大小的比例,实时传递给ProgressBar
  • 使用异步操作避免阻塞控制台主线程,让进度条动画流畅显示

修改后的完整代码

Program类(改为异步Main方法)

using System;
using System.Threading.Tasks;

class Program
{
    static async Task Main(string[] args)
    {
        Console.WriteLine("Source:");
        string sourcePath = Console.ReadLine();
        Console.WriteLine("Target:");
        string targetPath = Console.ReadLine();

        var copyTool = new Copy();
        await copyTool.CopyWithProgressAsync(sourcePath, targetPath);
        
        Console.ReadLine();
    }
}

Copy类(实现带进度跟踪的异步复制)

using System;
using System.IO;
using System.Threading.Tasks;

class Copy
{
    public async Task CopyWithProgressAsync(string sourcePath, string targetPath)
    {
        // 获取源文件总大小,用于计算进度比例
        var fileInfo = new FileInfo(sourcePath);
        long totalBytes = fileInfo.Length;
        long copiedBytes = 0;

        Console.WriteLine("Files are being copied...");

        // 绑定进度更新回调,实时同步到进度条
        using var progressBar = new ProgressBar();
        var progress = new Progress<double>(value =>
        {
            progressBar.Report(value);
        });

        // 分块读写文件,平衡性能与进度更新频率
        const int bufferSize = 4096;
        var buffer = new byte[bufferSize];

        using var sourceStream = new FileStream(sourcePath, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize, true);
        using var targetStream = new FileStream(targetPath, FileMode.Create, FileAccess.Write, FileShare.None, bufferSize, true);

        int bytesRead;
        while ((bytesRead = await sourceStream.ReadAsync(buffer, 0, bufferSize)) > 0)
        {
            await targetStream.WriteAsync(buffer, 0, bytesRead);
            copiedBytes += bytesRead;

            // 计算当前进度(已复制字节数/总字节数)
            double progressPercent = (double)copiedBytes / totalBytes;
            progress.Report(progressPercent);

            // 可选:微小延迟避免进度条更新过快(大文件可忽略)
            await Task.Delay(1);
        }

        Console.WriteLine("\nFile Copied Successfully!");
    }
}

ProgressBar类(保留你使用的实现)

// 放入你之前使用的ProgressBar类代码即可

关键说明

  • 异步IO操作ReadAsyncWriteAsync不会阻塞主线程,让控制台能实时响应进度条的更新
  • 进度计算:每次写入后更新已复制字节数,计算占总文件的比例,通过Progress<double>传递给进度条
  • 缓冲区大小:4096字节是常用的IO缓冲区大小,大文件可以调整为8192或更大,平衡复制速度与进度更新频率

这样修改后,进度条就会随着文件复制的过程同步更新,完全贴合真实的复制进度啦!

内容的提问来源于stack exchange,提问作者zadders

火山引擎 最新活动