Mercurial > repos > SharpZipLib
comparison Core/StreamUtils.cs @ 1:94e25b786321
Re #311: can't read ZIP file packed by Linux app Archive Manager/File Roller
Initial commit of clean SharpZipLib 0860 source. Only change is build paths.
author | IBBoard <dev@ibboard.co.uk> |
---|---|
date | Sat, 30 Oct 2010 14:03:17 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
0:d16ef17fa7bb | 1:94e25b786321 |
---|---|
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 | |
39 namespace ICSharpCode.SharpZipLib.Core | |
40 { | |
41 /// <summary> | |
42 /// Provides simple <see cref="Stream"/>" utilities. | |
43 /// </summary> | |
44 public sealed class StreamUtils | |
45 { | |
46 /// <summary> | |
47 /// Read from a <see cref="Stream"/> ensuring all the required data is read. | |
48 /// </summary> | |
49 /// <param name="stream">The stream to read.</param> | |
50 /// <param name="buffer">The buffer to fill.</param> | |
51 /// <seealso cref="ReadFully(Stream,byte[],int,int)"/> | |
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 /// <exception cref="ArgumentNullException">Required parameter is null</exception> | |
65 /// <exception cref="ArgumentOutOfRangeException"><paramref name="offset"/> and or <paramref name="count"/> are invalid.</exception> | |
66 /// <exception cref="EndOfStreamException">End of stream is encountered before all the data has been read.</exception> | |
67 static public void ReadFully(Stream stream, byte[] buffer, int offset, int count) | |
68 { | |
69 if ( stream == null ) { | |
70 throw new ArgumentNullException("stream"); | |
71 } | |
72 | |
73 if ( buffer == null ) { | |
74 throw new ArgumentNullException("buffer"); | |
75 } | |
76 | |
77 // Offset can equal length when buffer and count are 0. | |
78 if ( (offset < 0) || (offset > buffer.Length) ) { | |
79 throw new ArgumentOutOfRangeException("offset"); | |
80 } | |
81 | |
82 if ( (count < 0) || (offset + count > buffer.Length) ) { | |
83 throw new ArgumentOutOfRangeException("count"); | |
84 } | |
85 | |
86 while ( count > 0 ) { | |
87 int readCount = stream.Read(buffer, offset, count); | |
88 if ( readCount <= 0 ) { | |
89 throw new EndOfStreamException(); | |
90 } | |
91 offset += readCount; | |
92 count -= readCount; | |
93 } | |
94 } | |
95 | |
96 /// <summary> | |
97 /// Copy the contents of one <see cref="Stream"/> to another. | |
98 /// </summary> | |
99 /// <param name="source">The stream to source data from.</param> | |
100 /// <param name="destination">The stream to write data to.</param> | |
101 /// <param name="buffer">The buffer to use during copying.</param> | |
102 static public void Copy(Stream source, Stream destination, byte[] buffer) | |
103 { | |
104 if (source == null) { | |
105 throw new ArgumentNullException("source"); | |
106 } | |
107 | |
108 if (destination == null) { | |
109 throw new ArgumentNullException("destination"); | |
110 } | |
111 | |
112 if (buffer == null) { | |
113 throw new ArgumentNullException("buffer"); | |
114 } | |
115 | |
116 // Ensure a reasonable size of buffer is used without being prohibitive. | |
117 if (buffer.Length < 128) { | |
118 throw new ArgumentException("Buffer is too small", "buffer"); | |
119 } | |
120 | |
121 bool copying = true; | |
122 | |
123 while (copying) { | |
124 int bytesRead = source.Read(buffer, 0, buffer.Length); | |
125 if (bytesRead > 0) { | |
126 destination.Write(buffer, 0, bytesRead); | |
127 } | |
128 else { | |
129 destination.Flush(); | |
130 copying = false; | |
131 } | |
132 } | |
133 } | |
134 | |
135 /// <summary> | |
136 /// Copy the contents of one <see cref="Stream"/> to another. | |
137 /// </summary> | |
138 /// <param name="source">The stream to source data from.</param> | |
139 /// <param name="destination">The stream to write data to.</param> | |
140 /// <param name="buffer">The buffer to use during copying.</param> | |
141 /// <param name="progressHandler">The <see cref="ProgressHandler">progress handler delegate</see> to use.</param> | |
142 /// <param name="updateInterval">The minimum <see cref="TimeSpan"/> between progress updates.</param> | |
143 /// <param name="sender">The source for this event.</param> | |
144 /// <param name="name">The name to use with the event.</param> | |
145 /// <remarks>This form is specialised for use within #Zip to support events during archive operations.</remarks> | |
146 static public void Copy(Stream source, Stream destination, | |
147 byte[] buffer, ProgressHandler progressHandler, TimeSpan updateInterval, object sender, string name) | |
148 { | |
149 Copy(source, destination, buffer, progressHandler, updateInterval, sender, name, -1); | |
150 } | |
151 | |
152 /// <summary> | |
153 /// Copy the contents of one <see cref="Stream"/> to another. | |
154 /// </summary> | |
155 /// <param name="source">The stream to source data from.</param> | |
156 /// <param name="destination">The stream to write data to.</param> | |
157 /// <param name="buffer">The buffer to use during copying.</param> | |
158 /// <param name="progressHandler">The <see cref="ProgressHandler">progress handler delegate</see> to use.</param> | |
159 /// <param name="updateInterval">The minimum <see cref="TimeSpan"/> between progress updates.</param> | |
160 /// <param name="sender">The source for this event.</param> | |
161 /// <param name="name">The name to use with the event.</param> | |
162 /// <param name="fixedTarget">A predetermined fixed target value to use with progress updates. | |
163 /// If the value is negative the target is calculated by looking at the stream.</param> | |
164 /// <remarks>This form is specialised for use within #Zip to support events during archive operations.</remarks> | |
165 static public void Copy(Stream source, Stream destination, | |
166 byte[] buffer, | |
167 ProgressHandler progressHandler, TimeSpan updateInterval, | |
168 object sender, string name, long fixedTarget) | |
169 { | |
170 if (source == null) { | |
171 throw new ArgumentNullException("source"); | |
172 } | |
173 | |
174 if (destination == null) { | |
175 throw new ArgumentNullException("destination"); | |
176 } | |
177 | |
178 if (buffer == null) { | |
179 throw new ArgumentNullException("buffer"); | |
180 } | |
181 | |
182 // Ensure a reasonable size of buffer is used without being prohibitive. | |
183 if (buffer.Length < 128) { | |
184 throw new ArgumentException("Buffer is too small", "buffer"); | |
185 } | |
186 | |
187 if (progressHandler == null) { | |
188 throw new ArgumentNullException("progressHandler"); | |
189 } | |
190 | |
191 bool copying = true; | |
192 | |
193 DateTime marker = DateTime.Now; | |
194 long processed = 0; | |
195 long target = 0; | |
196 | |
197 if (fixedTarget >= 0) { | |
198 target = fixedTarget; | |
199 } | |
200 else if (source.CanSeek) { | |
201 target = source.Length - source.Position; | |
202 } | |
203 | |
204 // Always fire 0% progress.. | |
205 ProgressEventArgs args = new ProgressEventArgs(name, processed, target); | |
206 progressHandler(sender, args); | |
207 | |
208 bool progressFired = true; | |
209 | |
210 while (copying) { | |
211 int bytesRead = source.Read(buffer, 0, buffer.Length); | |
212 if (bytesRead > 0) { | |
213 processed += bytesRead; | |
214 progressFired = false; | |
215 destination.Write(buffer, 0, bytesRead); | |
216 } | |
217 else { | |
218 destination.Flush(); | |
219 copying = false; | |
220 } | |
221 | |
222 if (DateTime.Now - marker > updateInterval) { | |
223 progressFired = true; | |
224 marker = DateTime.Now; | |
225 args = new ProgressEventArgs(name, processed, target); | |
226 progressHandler(sender, args); | |
227 | |
228 copying = args.ContinueRunning; | |
229 } | |
230 } | |
231 | |
232 if (!progressFired) { | |
233 args = new ProgressEventArgs(name, processed, target); | |
234 progressHandler(sender, args); | |
235 } | |
236 } | |
237 | |
238 /// <summary> | |
239 /// Initialise an instance of <see cref="StreamUtils"></see> | |
240 /// </summary> | |
241 private StreamUtils() | |
242 { | |
243 // Do nothing. | |
244 } | |
245 } | |
246 } |