/
ProgressOperations.cs
96 lines (83 loc) · 3.91 KB
/
ProgressOperations.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Security.Cryptography;
namespace SLaks.Progression {
///<summary>Contains methods that perform useful operations and report progress.</summary>
public static class ProgressOperations {
///<summary>Copies one stream to another while reporting progress.</summary>
///<param name="from">The stream to copy from. This stream must be readable.</param>
///<param name="to">The stream to copy to. This stream must be writable.</param>
///<param name="progress">An IProgressReporter implementation to report the progress of the upload.</param>
///<returns>The number of bytes copied.</returns>
public static long CopyTo(this Stream from, Stream to, IProgressReporter progress) { return from.CopyTo(to, null, progress); }
///<summary>Copies one stream to another while reporting progress.</summary>
///<param name="from">The stream to copy from. This stream must be readable.</param>
///<param name="to">The stream to copy to. This stream must be writable.</param>
///<param name="length">The length of the source stream. This parameter is only used to report progress.</param>
///<param name="progress">An IProgressReporter implementation to report the progress of the upload.</param>
///<returns>The number of bytes copied.</returns>
public static long CopyTo(this Stream from, Stream to, long? length, IProgressReporter progress) {
if (from == null) throw new ArgumentNullException("from");
if (to == null) throw new ArgumentNullException("to");
if (!from.CanRead) throw new ArgumentException("Source stream must be readable", "from");
if (!to.CanWrite) throw new ArgumentException("Destination stream must be writable", "to");
if (progress != null) {
if (length == null) {
try {
length = from.Length;
} catch (NotSupportedException) { progress.Progress = null; }
}
if (length == null)
progress.Progress = null;
else
progress.Maximum = length.Value;
}
progress = progress ?? new EmptyProgressReporter();
long totalCopied = 0;
var buffer = new byte[4096];
while (true) {
var bytesRead = from.Read(buffer, 0, buffer.Length);
if (length != null) progress.Progress = totalCopied;
if (progress.WasCanceled) return -1;
totalCopied += bytesRead;
if (bytesRead == 0) return totalCopied;
to.Write(buffer, 0, bytesRead);
}
}
///<summary>Calculates a cryptographic hashcode of a file while reporting progress.</summary>
///<returns>The hash of the data, or null if the user clicked cancel.</returns>
public static byte[] ComputeHash(this HashAlgorithm hasher, string fileName, IProgressReporter progress) {
using (var stream = File.OpenRead(fileName))
return ComputeHash(hasher, stream, progress);
}
///<summary>Calculates a cryptographic hashcode of a stream while reporting progress.</summary>
///<returns>The hash of the data, or null if the user clicked cancel.</returns>
public static byte[] ComputeHash(this HashAlgorithm hasher, Stream stream, IProgressReporter progress) {
if (hasher == null) throw new ArgumentNullException("hasher");
if (stream == null) throw new ArgumentNullException("stream");
if (progress != null) {
try {
progress.Maximum = stream.Length;
} catch (NotSupportedException) { progress.Progress = null; }
}
progress = progress ?? new EmptyProgressReporter();
long totalCopied = 0;
var buffer = new byte[4096];
while (true) {
var bytesRead = stream.Read(buffer, 0, buffer.Length);
if (progress.Progress != null) progress.Progress = totalCopied;
if (progress.WasCanceled) return null;
totalCopied += bytesRead;
if (bytesRead == 0) break;
hasher.TransformBlock(buffer, 0, bytesRead, null, 0);
}
hasher.TransformFinalBlock(new byte[0], 0, 0);
var retVal = (byte[])hasher.Hash.Clone();
hasher.Initialize();
return retVal;
}
}
}