C# - WPF实战:线程化复制文件并显示进度条(当然C#的WinForm也可以实现,只需小小的改动一下)

目录:

引言

两种复制的用法

Copy()

CopyTo()

一、布局

二、主程序

1. 定义变量:

2. 选择文件

3. 复制

(1) 复制信息类

(2) 复制文件方法

(3) 事件触发

4. 更新进度条

5. 打开本地文件夹

6. 关闭窗口确认

三、完整代码

四、效果图


引言:

汁粥嗦粽,C#呢,有n种复制文件的方法,如Copy()方法,CopyTo()方法.

两种复制的用法:

1. Copy():

File.Copy(SourcePath, TargetPath, IsOverWrite);
 

(1) SourcePath:要复制的文件路径                类型:string

(2) TargetPath:复制后文件存放文件夹                类型:string

(3) IsOverWrite:是否覆盖写入                类型:bool

2. CopyTo():

File Source = new File(SourcePath);

Source.CopyTo(TargetPath, IsOverWrite);

(1) SourcePath:要复制的文件路径                类型:string

(2) TargetPath:复制后文件存放文件夹                类型:string

(3) IsOverWrite:是否覆盖写入                类型:bool

(4) Source:File类的对象                类型:File

但是它们都不能显示进度条.

对啊,这一搜,没有一个趁我心的,难道这个就无解了吗?

当然不.

所以我做了这个教程.

实战引入:我要做一个复制文件的WPF项目,既追求效率、性能还需要进度条显示.

一、布局

先在你要复制的Window中(我这里是MainWindow.xaml),创建

用到的所有控件
序号类型名称作用
1.TextBoxPathShower显示选择的路径
2.ButtonSelect打开OpenFileDialog选择文件
3.ButtonCopyBtn点击后复制文件
4.TextBoxDisplayCopyInfo显示复制信息
5.ProgressBarCopyProgress显示复制进度
6.ButtonOpenDirectory

打开复制后的文件夹

可以自定义名称,但是在后面的代码部分要跟着改.

这里还是贴出我的MainWindow.xaml

<Window x:Name="MainWindow1" x:Class="Main.UI.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:Main.UI"
        mc:Ignorable="d"
        Title="Main.UI" Height="720" Width="1280" ResizeMode="NoResize" WindowStartupLocation="CenterScreen" FontSize="16" Closing="MainWindow_Closing">
    <Grid>
        <Button x:Name="CopyBtn" Content="复制" Margin="70,145,944,489" Click="CopyBtn_Click"/>
        <TextBox x:Name="PathShower" Margin="70,70,944,565" TextWrapping="Wrap" Height="70.0766666666667" UndoLimit="1000">
            <TextBox.Resources>
                <VisualBrush x:Key="HelpBrush" TileMode="None" Opacity="0.3" Stretch="None" AlignmentX="Left">
                    <VisualBrush.Visual>
                        <TextBlock FontStyle="Italic" Text="[Click Botton Or Input There]"/>
                    </VisualBrush.Visual>
                </VisualBrush>
            </TextBox.Resources>
            <TextBox.Style>
                <Style TargetType="TextBox">
                    <Style.Triggers>
                        <Trigger Property="Text" Value="{x:Null}">
                            <Setter Property="Background" Value="{StaticResource HelpBrush}"/>
                        </Trigger>
                        <Trigger Property="Text" Value="">
                            <Setter Property="Background" Value="{StaticResource HelpBrush}"/>
                        </Trigger>
                    </Style.Triggers>
                </Style>
            </TextBox.Style>
        </TextBox>
        <Button x:Name="Select" Content="选择..." Margin="341,70,869,564" Click="Select_Click"/>
        <ProgressBar x:Name="CopyProgress" Margin="70,295,944,339" d:LayoutOverrides="VerticalAlignment"/>
        <TextBox x:Name="DisplayCopyInfo" Margin="70,220,944,415" TextWrapping="Wrap" Text="就绪" FontSize="16" Height="70.0766666666667"/>
        <Button x:Name="OpenDirectory" Content="打开复制后文件的存放文件夹" Margin="70,370,944,264" Click="OpenDirectory_Click"/>
    </Grid>
</Window>

二、主程序

1. 定义变量:

public string FilePath = string.Empty;
public string LocalPath = string.Empty;
private string Creator = Environment.CurrentDirectory + @"\res";
private Thread CopyThread;

注:

(1) FilePath:要复制的文件路径

(2) LocalPath:复制后文件存放文件夹

(3) Creator:当文件夹不存在时,创建该文件夹所用到的字符串

(4) CopyThread:复制线程

2. 选择文件

private void Select_Click(object sender, RoutedEventArgs e)
{
	OpenFileDialog openFileDialog = new OpenFileDialog();
	openFileDialog.Title = "请选择要上传的文件.";
	openFileDialog.Filter = "所有类型的文件|*.*";
	openFileDialog.FileName = string.Empty;
	openFileDialog.FilterIndex = 1;
	openFileDialog.Multiselect = false;
	openFileDialog.RestoreDirectory = false;
	openFileDialog.CheckFileExists= true;
	try
	{
		openFileDialog.ShowDialog();
		FilePath = Path.GetFullPath(openFileDialog.FileName);
		if (!Directory.Exists(Creator)) Directory.CreateDirectory(Creator);
		LocalPath = Environment.CurrentDirectory + @"\res\" + Path.GetFileName(openFileDialog.FileName);
		PathShower.Text = LocalPath;
	}
	catch (ArgumentException)
	{
		MessageBox.Show("请选择一个文件.");
	}
	catch (Exception)
	{
		MessageBox.Show("请合理输入文件路径.");
	}

}

注:

这里主要运用了OpenFileDialog用于选择文件(当然文本框也可以).

3. 复制

(1) 复制信息类

public class CopyFileInfo
{
    public string SourcePath { get; set; }
    public string TargetPath { get; set; }        
}

注:

原理很简单,就是定义两个属性,不多赘述.

(2) 复制文件方法

private void CopyFile(object obj)
{
    CopyFileInfo? c = obj as CopyFileInfo;
    CopyFile(c.SourcePath, c.TargetPath);
}
private void CopyFile(string SourcePath, string TargetPath)
{
    FileInfo F = new FileInfo(SourcePath);
    FileStream FSR = F.OpenRead();
    FileStream FSW = File.Create(TargetPath);
    long FileLength = F.Length;
    byte[] Buffer = new byte[2097152];
    int n = 0;
    while (true)
    {
        DisplayCopyInfo.Dispatcher.BeginInvoke(DispatcherPriority.SystemIdle,
        new Action<long, long>(UpdateCopyProgress), FileLength, FSR.Position);
        n=FSR.Read(Buffer, 0, 2097152); 
        if (n==0)
        {
            break;
        }
        FSW.Write(Buffer, 0, n);
        FSW.Flush();
	}
    FSR.Close();
    FSW.Close();
}

这里就是一个很基本的复制文件的方法了.

注:

byte[] Buffer = new byte[2097152];   

这行代码中的2097152代表每次复制文件的长度,可以改动,但不能太大,会报错.    这个速度已经很快了,没有特殊需求默认即可.

(3) 事件触发

private void CopyBtn_Click(object sender, RoutedEventArgs e)
{
	try
	{
		CopyProgress.Maximum = new FileInfo(FilePath).Length;
		//保存文件信息
		CopyFileInfo copy = new CopyFileInfo() { SourcePath = FilePath, TargetPath = LocalPath };
		//异步调用
		CopyThread = new Thread(new ParameterizedThreadStart(CopyFile));
        //实例化线程
		CopyThread.Start(copy);
        //启动线程
	}
	catch
	{
		MessageBox.Show("请选择或输入文件路径及名称!");
	}
}

4. 更新进度条

private void UpdateCopyProgress(long FileLength, long CurrentLength)
{
	DisplayCopyInfo.Text = string.Format("总长度:{0}, 已复制:{1}", FileLength, CurrentLength);          
	CopyProgress.Value = CurrentLength;
}

注:

这里使用了ProgressBar类型的CopyProgress对象的属性Value.

5. 打开本地文件夹

public static void command(string input)
{
	Process CmdProcess = new Process();
	CmdProcess.StartInfo.FileName = "cmd.exe";
	CmdProcess.StartInfo.CreateNoWindow = true;
	CmdProcess.StartInfo.UseShellExecute = false;
	CmdProcess.StartInfo.RedirectStandardInput = true;
	CmdProcess.StartInfo.RedirectStandardOutput = true;
	CmdProcess.StartInfo.RedirectStandardError = true;
	CmdProcess.StartInfo.Arguments = "/c " + input;
	CmdProcess.Start();
	CmdProcess.WaitForExit();
	CmdProcess.Close();
}

private void OpenDirectory_Click(object sender, RoutedEventArgs e)
{
	if (!Directory.Exists(Creator)) Directory.CreateDirectory(Creator);
	command("explorer \"" + Environment.CurrentDirectory + "\\res\"");
}

注:

这里使用了Process类来达到打开文件夹的效果.

6. 关闭窗口确认

private void MainWindow_Closing(object sender, CancelEventArgs e)
{
	MessageBoxResult result = MessageBox.Show("是否退出?", "退出确认", MessageBoxButton.OKCancel, MessageBoxImage.Question);
	if (result == MessageBoxResult.Cancel)
	{
		e.Cancel = true;
	}
	else
	{
		Environment.Exit(0);
	}
}

注:

需要在xaml里添加关闭事件:Closing="MainWindow_Closing".

三、完整代码

using Microsoft.Win32;
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Threading;

namespace Advanced_Copy
{
	public partial class MainWindow : Window
	{

		public string FilePath = string.Empty;
		public string LocalPath = string.Empty;
		private string Creator = Environment.CurrentDirectory + @"\res";
		private Thread CopyThread;

		public MainWindow()
		{
			InitializeComponent();
		}

		private void CopyBtn_Click(object sender, RoutedEventArgs e)
		{
			try
			{
				CopyProgress.Maximum = new FileInfo(FilePath).Length;
				CopyFileInfo copy = new CopyFileInfo() { SourcePath = FilePath, TargetPath = LocalPath };
				CopyThread = new Thread(new ParameterizedThreadStart(CopyFile));
				CopyThread.Start(copy);
			}
			catch
			{
				MessageBox.Show("请选择或输入文件路径及名称!");
			}
		}

		private void Select_Click(object sender, RoutedEventArgs e)
		{
			OpenFileDialog openFileDialog = new OpenFileDialog();
			openFileDialog.Title = "请选择要上传的文件.";
			openFileDialog.Filter = "所有类型的文件|*.*";
			openFileDialog.FileName = string.Empty;
			openFileDialog.FilterIndex = 1;
			openFileDialog.Multiselect = false;
			openFileDialog.RestoreDirectory = false;
			openFileDialog.CheckFileExists= true;
			try
			{
				openFileDialog.ShowDialog();
				FilePath = Path.GetFullPath(openFileDialog.FileName);
				if (!Directory.Exists(Creator)) Directory.CreateDirectory(Creator);
				LocalPath = Environment.CurrentDirectory + @"\res\" + Path.GetFileName(openFileDialog.FileName);
				PathShower.Text = LocalPath;
			}
			catch (ArgumentException)
			{
				MessageBox.Show("请选择一个文件.");
			}
			catch (Exception)
			{
				MessageBox.Show("请合理输入文件路径.");
			}

		}

		private void CopyFile(object obj)
	    {
	        CopyFileInfo? c = obj as CopyFileInfo;
	        CopyFile(c.SourcePath, c.TargetPath);
	    }
		private void CopyFile(string SourcePath, string TargetPath)
        {
            FileInfo F = new FileInfo(SourcePath);
            FileStream FSR = F.OpenRead();
            FileStream FSW = File.Create(TargetPath);
            long FileLength = F.Length;
            byte[] Buffer = new byte[2097152];
            int n = 0;
            
            while (true)
            {
                DisplayCopyInfo.Dispatcher.BeginInvoke(DispatcherPriority.SystemIdle,
                new Action<long, long>(UpdateCopyProgress), FileLength, FSR.Position);
                

                n=FSR.Read(Buffer, 0, 2097152); 
                if (n==0)
                {
                    break;
                }
                FSW.Write(Buffer, 0, n);
                FSW.Flush();
			}
            FSR.Close();
            FSW.Close();
        }

		private void UpdateCopyProgress(long FileLength, long CurrentLength)
		{
			DisplayCopyInfo.Text = string.Format("总长度:{0}, 已复制:{1}", FileLength, CurrentLength);
			CopyProgress.Value = CurrentLength;
		}

		private void OpenDirectory_Click(object sender, RoutedEventArgs e)
		{
			if (!Directory.Exists(Creator)) Directory.CreateDirectory(Creator);
			Command.command("explorer \"" + Environment.CurrentDirectory + "\\res\"");
		}

		private void MainWindow_Closing(object sender, CancelEventArgs e)
		{
			MessageBoxResult result = MessageBox.Show("是否退出?", "退出确认", MessageBoxButton.OKCancel, MessageBoxImage.Question);
			if (result == MessageBoxResult.Cancel)
			{
				e.Cancel = true;
			}
			else
			{
				Environment.Exit(0);
			}
		}

	}



	public class CopyFileInfo
	{
	        public string SourcePath { get; set; }
	        public string TargetPath { get; set; }        
	}



}

四、效果图

教程到此结束,感谢参考!

Made By HXLyxx On 2022.12.15

  • 6
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值