本篇文章主要介绍了"filestream C#基础-FileStream实现多线程断点续传",主要涉及到filestream方面的内容,对于.NETjrs看球网直播吧_低调看直播体育app软件下载_低调看体育直播感兴趣的同学可以参考一下:
一、前言 网上有许多的多线程断点续传操作,但总是写的很云里雾里,或者写的比较坑长。由于这几个月要负责公司的在线升级项目,所以正好用到 代...
一、前言
网上有许多的多线程断点续传操作,但总是写的很云里雾里,或者写的比较坑长。由于这几个月要负责公司的在线升级项目,所以正好用到
代码如下:
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Text;
5using System.IO;
6using System.Threading;
7using System.Threading.Tasks;
8 9namespace ConsoleStream
10{
11class Program
12 {
13staticvoid Main(string[] args)
14 {
15string LocalSavePath = @"E:\Test\Test\local\1.msi"; //本地目标文件路径 16 17 System.IO.FileInfo SeverFilePath = new FileInfo(@"E:\Test\Test\server\1.msi"); //服务器待文件路径 18long FileLength = SeverFilePath.Length; //待下载文件大小 19 20 21 Console.WriteLine("Start Configuration");
22int PackCount = 0; //初始化数据包个数 23 24long PackSize = 10240000; //数据包大小 25 26if (FileLength % PackSize> 0)
27 {
28 PackCount = (int)(FileLength / PackSize) + 1;
29 }
30 31else 32 {
33 PackCount = (int)(FileLength / PackSize);
34 }
35 36 37 Console.WriteLine("Start Recieve");
38var tasks = new Task[PackCount]; //多线程任务 39 40for (int index = 0; index < PackCount; index++)
41 {
42 43 44int Threadindex = index; //这步很关键,在Task()里的绝对不能直接使用index 45var task = new Task(() =>
46 {
47string tempfilepath = @"E:\Test\Test\temp\" + "QS_" + Threadindex.ToString() + "_" + PackCount.ToString(); //临时文件路径 48 49using (System.IO.FileStream tempstream = new System.IO.FileStream(tempfilepath, FileMode.Create, FileAccess.Write, FileShare.Write))
50 {
51int length = (int)Math.Min(PackSize, FileLength - Threadindex * PackSize);
52 53var bytes = GetFile(Threadindex, length);
54 55 tempstream.Write(bytes, 0, length);
56 tempstream.Flush();
57 tempstream.Close();
58 tempstream.Dispose();
59 }
60 });
61 tasks[Threadindex] = task;
62 task.Start();
63 }
64 65 Task.WaitAll(tasks); //等待所有线程完成 66 Console.WriteLine("Recieve End");
67 68 69//检测有哪些数据包未下载 70 Console.WriteLine("Start Compare");
71 DirectoryInfo TempDir = new DirectoryInfo(@"E:\Test\Test\temp"); //临时文件夹路径 72 List<string> Comparefiles = new List<string>();
73bool hasfile = false;
74for (int i = 0; i < PackCount; i++)
75 {
76foreach (FileInfo Tempfile in TempDir.GetFiles())
77 {
78if (Tempfile.Name.Split('_')[1] == i.ToString())
79 {
80 hasfile = true;
81break;
82 }
83 }
84if (hasfile == false)
85 {
86 Comparefiles.Add(i.ToString());
87 }
88 }
89 90//最后补上这些缺失的文件 91if (Comparefiles.Count > 0)
92 {
93foreach (string com_index in Comparefiles)
94 {
95string tempfilepath = @"E:\Test\Test\temp\" + "QS_" + com_index.ToString() + "_" + PackCount.ToString();
96using (System.IO.FileStream Compstream = new System.IO.FileStream(tempfilepath, FileMode.Create, FileAccess.Write, FileShare.Write))
97 {
98int length = (int)Math.Min(PackSize, FileLength - Convert.ToInt32(com_index) * PackSize);
99var bytes = GetFile(Convert.ToInt32(com_index), length);
100 Compstream.Write(bytes, 0, length);
101 Compstream.Flush();
102 Compstream.Close();
103 Compstream.Dispose();
104 }
105 }
106107 }
108 Console.WriteLine("Compare End");
109110111//准备将临时文件融合并写到1.msi中112 Console.WriteLine("Start Write");
113using (System.IO.FileStream writestream = new System.IO.FileStream(LocalSavePath, FileMode.Create, FileAccess.Write, FileShare.Write))
114 {
115foreach (FileInfo Tempfile in TempDir.GetFiles())
116 {
117using (System.IO.FileStream readTempStream = new System.IO.FileStream(Tempfile.FullName, System.IO.FileMode.Open, System.IO.FileAccess.Read, FileShare.ReadWrite))
118 {
119long onefileLength = Tempfile.Length;
120byte[] buffer = newbyte[Convert.ToInt32(onefileLength)];
121 readTempStream.Read(buffer, 0, Convert.ToInt32(onefileLength));
122 writestream.Write(buffer, 0, Convert.ToInt32(onefileLength));
123 }
124 }
125 writestream.Flush();
126 writestream.Close();
127 writestream.Dispose();
128 }
129 Console.WriteLine("Write End");
130131132133//删除临时文件134 Console.WriteLine("Start Delete Temp Files");
135foreach (FileInfo Tempfile in TempDir.GetFiles())
136 {
137 Tempfile.Delete();
138 }
139 Console.WriteLine("Delete Success");
140 Console.ReadKey();
141 }
142143144//这个方法可以放到Remoting或者WCF服务中去,然后本地调用该方法即可实现多线程断点续传145publicstaticbyte[] GetFile(int start, int length)
146 {
147string SeverFilePath = @"E:\Test\Test\server\1.msi";
148using (System.IO.FileStream ServerStream = new System.IO.FileStream(SeverFilePath, System.IO.FileMode.Open, System.IO.FileAccess.Read, FileShare.ReadWrite,1024,true))
149 {
150byte[] buffer = newbyte[length];
151 ServerStream.Position = start;
152 ServerStream.Read(buffer, 0, length);
153return buffer;
154 }
155 }
156157158 }
159 }
二、讨论