root / trunk / hammock / src / net35 / ICSharpCode.SharpZipLib.Silverlight / Core / StreamUtils.cs @ 0eea575a
History | View | Annotate | Download (8 kB)
1 |
// StreamUtils.cs |
---|---|
2 |
// |
3 |
// Copyright 2005 John Reilly |
4 |
// |
5 |
// This program is free software; you can redistribute it and/or |
6 |
// modify it under the terms of the GNU General Public License |
7 |
// as published by the Free Software Foundation; either version 2 |
8 |
// of the License, or (at your option) any later version. |
9 |
// |
10 |
// This program is distributed in the hope that it will be useful, |
11 |
// but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 |
// GNU General Public License for more details. |
14 |
// |
15 |
// You should have received a copy of the GNU General Public License |
16 |
// along with this program; if not, write to the Free Software |
17 |
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
18 |
// |
19 |
// Linking this library statically or dynamically with other modules is |
20 |
// making a combined work based on this library. Thus, the terms and |
21 |
// conditions of the GNU General Public License cover the whole |
22 |
// combination. |
23 |
// |
24 |
// As a special exception, the copyright holders of this library give you |
25 |
// permission to link this library with independent modules to produce an |
26 |
// executable, regardless of the license terms of these independent |
27 |
// modules, and to copy and distribute the resulting executable under |
28 |
// terms of your choice, provided that you also meet, for each linked |
29 |
// independent module, the terms and conditions of the license of that |
30 |
// module. An independent module is a module which is not derived from |
31 |
// or based on this library. If you modify this library, you may extend |
32 |
// this exception to your version of the library, but you are not |
33 |
// obligated to do so. If you do not wish to do so, delete this |
34 |
// exception statement from your version. |
35 |
|
36 |
using System; |
37 |
using System.IO; |
38 |
using ICSharpCode.SharpZipLib.Silverlight.Core; |
39 |
|
40 |
namespace ICSharpCode.SharpZipLib.Silverlight.Core |
41 |
{ |
42 |
/// <summary> |
43 |
/// Provides simple <see cref="Stream"/>" utilities. |
44 |
/// </summary> |
45 |
public static class StreamUtils |
46 |
{ |
47 |
/// <summary> |
48 |
/// Read from a <see cref="Stream"/> ensuring all the required data is read. |
49 |
/// </summary> |
50 |
/// <param name="stream">The stream to read.</param> |
51 |
/// <param name="buffer">The buffer to fill.</param> |
52 |
static public void ReadFully(Stream stream, byte[] buffer) |
53 |
{ |
54 |
ReadFully(stream, buffer, 0, buffer.Length); |
55 |
} |
56 |
|
57 |
/// <summary> |
58 |
/// Read from a <see cref="Stream"/>" ensuring all the required data is read. |
59 |
/// </summary> |
60 |
/// <param name="stream">The stream to read data from.</param> |
61 |
/// <param name="buffer">The buffer to store data in.</param> |
62 |
/// <param name="offset">The offset at which to begin storing data.</param> |
63 |
/// <param name="count">The number of bytes of data to store.</param> |
64 |
static public void ReadFully(Stream stream, byte[] buffer, int offset, int count) |
65 |
{ |
66 |
if ( stream == null ) { |
67 |
throw new ArgumentNullException("stream"); |
68 |
} |
69 |
|
70 |
if ( buffer == null ) { |
71 |
throw new ArgumentNullException("buffer"); |
72 |
} |
73 |
|
74 |
// Offset can equal length when buffer and count are 0. |
75 |
if ( (offset < 0) || (offset > buffer.Length) ) { |
76 |
throw new ArgumentOutOfRangeException("offset"); |
77 |
} |
78 |
|
79 |
if ( (count < 0) || (offset + count > buffer.Length) ) { |
80 |
throw new ArgumentOutOfRangeException("count"); |
81 |
} |
82 |
|
83 |
while ( count > 0 ) { |
84 |
int readCount = stream.Read(buffer, offset, count); |
85 |
if ( readCount <= 0 ) { |
86 |
throw new EndOfStreamException(); |
87 |
} |
88 |
offset += readCount; |
89 |
count -= readCount; |
90 |
} |
91 |
} |
92 |
|
93 |
/// <summary> |
94 |
/// Copy the contents of one <see cref="Stream"/> to another. |
95 |
/// </summary> |
96 |
/// <param name="source">The stream to source data from.</param> |
97 |
/// <param name="destination">The stream to write data to.</param> |
98 |
/// <param name="buffer">The buffer to use during copying.</param> |
99 |
/// <param name="progressHandler">The <see cref="ProgressHandler">progress handler delegate</see> to use.</param> |
100 |
/// <param name="updateInterval">The minimum <see cref="TimeSpan"/> between progress updates.</param> |
101 |
/// <param name="sender">The source for this event.</param> |
102 |
/// <param name="name">The name to use with the event.</param> |
103 |
static public void Copy(Stream source, Stream destination, |
104 |
byte[] buffer, ProgressHandler progressHandler, TimeSpan updateInterval, object sender, string name) |
105 |
{ |
106 |
if (source == null) { |
107 |
throw new ArgumentNullException("source"); |
108 |
} |
109 |
|
110 |
if (destination == null) { |
111 |
throw new ArgumentNullException("destination"); |
112 |
} |
113 |
|
114 |
if (buffer == null) { |
115 |
throw new ArgumentNullException("buffer"); |
116 |
} |
117 |
|
118 |
// Ensure a reasonable size of buffer is used without being prohibitive. |
119 |
if (buffer.Length < 128) { |
120 |
throw new ArgumentException("Buffer is too small", "buffer"); |
121 |
} |
122 |
|
123 |
if (progressHandler == null) { |
124 |
throw new ArgumentNullException("progressHandler"); |
125 |
} |
126 |
|
127 |
bool copying = true; |
128 |
|
129 |
DateTime marker = DateTime.Now; |
130 |
long processed = 0; |
131 |
long target = 0; |
132 |
|
133 |
if (source.CanSeek) { |
134 |
target = source.Length - source.Position; |
135 |
} |
136 |
|
137 |
// Always fire 0% progress.. |
138 |
var args = new ProgressEventArgs(name, processed, target); |
139 |
progressHandler(sender, args); |
140 |
|
141 |
bool completeFired = false; |
142 |
|
143 |
while (copying) { |
144 |
int bytesRead = source.Read(buffer, 0, buffer.Length); |
145 |
if (bytesRead > 0) { |
146 |
processed += bytesRead; |
147 |
destination.Write(buffer, 0, bytesRead); |
148 |
} |
149 |
else { |
150 |
destination.Flush(); |
151 |
copying = false; |
152 |
} |
153 |
|
154 |
if (DateTime.Now - marker > updateInterval) { |
155 |
completeFired = (processed == target); |
156 |
marker = DateTime.Now; |
157 |
args = new ProgressEventArgs(name, processed, target); |
158 |
progressHandler(sender, args); |
159 |
|
160 |
copying = args.ContinueRunning; |
161 |
} |
162 |
} |
163 |
|
164 |
if (!completeFired) { |
165 |
args = new ProgressEventArgs(name, processed, target); |
166 |
progressHandler(sender, args); |
167 |
} |
168 |
} |
169 |
|
170 |
/// <summary> |
171 |
/// Copy the contents of one <see cref="Stream"/> to another. |
172 |
/// </summary> |
173 |
/// <param name="source">The stream to source data from.</param> |
174 |
/// <param name="destination">The stream to write data to.</param> |
175 |
/// <param name="buffer">The buffer to use during copying.</param> |
176 |
static public void Copy(Stream source, Stream destination, byte[] buffer) |
177 |
{ |
178 |
if ( source == null ) { |
179 |
throw new ArgumentNullException("source"); |
180 |
} |
181 |
|
182 |
if ( destination == null ) { |
183 |
throw new ArgumentNullException("destination"); |
184 |
} |
185 |
|
186 |
if ( buffer == null ) { |
187 |
throw new ArgumentNullException("buffer"); |
188 |
} |
189 |
|
190 |
// Ensure a reasonable size of buffer is used without being prohibitive. |
191 |
if ( buffer.Length < 128 ) { |
192 |
throw new ArgumentException("Buffer is too small", "buffer"); |
193 |
} |
194 |
|
195 |
bool copying = true; |
196 |
|
197 |
while ( copying ) { |
198 |
int bytesRead = source.Read(buffer, 0, buffer.Length); |
199 |
if ( bytesRead > 0 ) { |
200 |
destination.Write(buffer, 0, bytesRead); |
201 |
} |
202 |
else { |
203 |
destination.Flush(); |
204 |
copying = false; |
205 |
} |
206 |
} |
207 |
} |
208 |
} |
209 |
} |