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 }