1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.apache.commons.net.io;
17
18 import java.io.IOException;
19 import java.io.InputStream;
20 import java.io.OutputStream;
21 import java.io.Reader;
22 import java.io.Writer;
23
24 /***
25 * The Util class cannot be instantiated and stores short static convenience
26 * methods that are often quite useful.
27 * <p>
28 * <p>
29 * @see CopyStreamException
30 * @see CopyStreamListener
31 * @see CopyStreamAdapter
32 * @author Daniel F. Savarese
33 ***/
34
35 public final class Util
36 {
37 /***
38 * The default buffer size used by {@link #copyStream copyStream }
39 * and {@link #copyReader copyReader }. It's value is 1024.
40 ***/
41 public static final int DEFAULT_COPY_BUFFER_SIZE = 1024;
42
43
44 private Util()
45 { }
46
47
48 /***
49 * Copies the contents of an InputStream to an OutputStream using a
50 * copy buffer of a given size and notifies the provided
51 * CopyStreamListener of the progress of the copy operation by calling
52 * its bytesTransferred(long, int) method after each write to the
53 * destination. If you wish to notify more than one listener you should
54 * use a CopyStreamAdapter as the listener and register the additional
55 * listeners with the CopyStreamAdapter.
56 * <p>
57 * The contents of the InputStream are
58 * read until the end of the stream is reached, but neither the
59 * source nor the destination are closed. You must do this yourself
60 * outside of the method call. The number of bytes read/written is
61 * returned.
62 * <p>
63 * @param source The source InputStream.
64 * @param dest The destination OutputStream.
65 * @param bufferSize The number of bytes to buffer during the copy.
66 * @param streamSize The number of bytes in the stream being copied.
67 * Should be set to CopyStreamEvent.UNKNOWN_STREAM_SIZE if unknown.
68 * @param listener The CopyStreamListener to notify of progress. If
69 * this parameter is null, notification is not attempted.
70 * @param flush Whether to flush the output stream after every
71 * write. This is necessary for interactive sessions that rely on
72 * buffered streams. If you don't flush, the data will stay in
73 * the stream buffer.
74 * @exception CopyStreamException If an error occurs while reading from the
75 * source or writing to the destination. The CopyStreamException
76 * will contain the number of bytes confirmed to have been
77 * transferred before an
78 * IOException occurred, and it will also contain the IOException
79 * that caused the error. These values can be retrieved with
80 * the CopyStreamException getTotalBytesTransferred() and
81 * getIOException() methods.
82 ***/
83 public static final long copyStream(InputStream source, OutputStream dest,
84 int bufferSize, long streamSize,
85 CopyStreamListener listener,
86 boolean flush)
87 throws CopyStreamException
88 {
89 int bytes;
90 long total;
91 byte[] buffer;
92
93 buffer = new byte[bufferSize];
94 total = 0;
95
96 try
97 {
98 while ((bytes = source.read(buffer)) != -1)
99 {
100
101
102
103 if (bytes == 0)
104 {
105 bytes = source.read();
106 if (bytes < 0)
107 break;
108 dest.write(bytes);
109 if(flush)
110 dest.flush();
111 ++total;
112 if (listener != null)
113 listener.bytesTransferred(total, 1, streamSize);
114 continue;
115 }
116
117 dest.write(buffer, 0, bytes);
118 if(flush)
119 dest.flush();
120 total += bytes;
121 if (listener != null)
122 listener.bytesTransferred(total, bytes, streamSize);
123 }
124 }
125 catch (IOException e)
126 {
127 throw new CopyStreamException("IOException caught while copying.",
128 total, e);
129 }
130
131 return total;
132 }
133
134
135 /***
136 * Copies the contents of an InputStream to an OutputStream using a
137 * copy buffer of a given size and notifies the provided
138 * CopyStreamListener of the progress of the copy operation by calling
139 * its bytesTransferred(long, int) method after each write to the
140 * destination. If you wish to notify more than one listener you should
141 * use a CopyStreamAdapter as the listener and register the additional
142 * listeners with the CopyStreamAdapter.
143 * <p>
144 * The contents of the InputStream are
145 * read until the end of the stream is reached, but neither the
146 * source nor the destination are closed. You must do this yourself
147 * outside of the method call. The number of bytes read/written is
148 * returned.
149 * <p>
150 * @param source The source InputStream.
151 * @param dest The destination OutputStream.
152 * @param bufferSize The number of bytes to buffer during the copy.
153 * @param streamSize The number of bytes in the stream being copied.
154 * Should be set to CopyStreamEvent.UNKNOWN_STREAM_SIZE if unknown.
155 * @param listener The CopyStreamListener to notify of progress. If
156 * this parameter is null, notification is not attempted.
157 * @exception CopyStreamException If an error occurs while reading from the
158 * source or writing to the destination. The CopyStreamException
159 * will contain the number of bytes confirmed to have been
160 * transferred before an
161 * IOException occurred, and it will also contain the IOException
162 * that caused the error. These values can be retrieved with
163 * the CopyStreamException getTotalBytesTransferred() and
164 * getIOException() methods.
165 ***/
166 public static final long copyStream(InputStream source, OutputStream dest,
167 int bufferSize, long streamSize,
168 CopyStreamListener listener)
169 throws CopyStreamException
170 {
171 return copyStream(source, dest, bufferSize, streamSize, listener,
172 true);
173 }
174
175
176 /***
177 * Copies the contents of an InputStream to an OutputStream using a
178 * copy buffer of a given size. The contents of the InputStream are
179 * read until the end of the stream is reached, but neither the
180 * source nor the destination are closed. You must do this yourself
181 * outside of the method call. The number of bytes read/written is
182 * returned.
183 * <p>
184 * @param source The source InputStream.
185 * @param dest The destination OutputStream.
186 * @return The number of bytes read/written in the copy operation.
187 * @exception CopyStreamException If an error occurs while reading from the
188 * source or writing to the destination. The CopyStreamException
189 * will contain the number of bytes confirmed to have been
190 * transferred before an
191 * IOException occurred, and it will also contain the IOException
192 * that caused the error. These values can be retrieved with
193 * the CopyStreamException getTotalBytesTransferred() and
194 * getIOException() methods.
195 ***/
196 public static final long copyStream(InputStream source, OutputStream dest,
197 int bufferSize)
198 throws CopyStreamException
199 {
200 return copyStream(source, dest, bufferSize,
201 CopyStreamEvent.UNKNOWN_STREAM_SIZE, null);
202 }
203
204
205 /***
206 * Same as <code> copyStream(source, dest, DEFAULT_COPY_BUFFER_SIZE); </code>
207 ***/
208 public static final long copyStream(InputStream source, OutputStream dest)
209 throws CopyStreamException
210 {
211 return copyStream(source, dest, DEFAULT_COPY_BUFFER_SIZE);
212 }
213
214
215 /***
216 * Copies the contents of a Reader to a Writer using a
217 * copy buffer of a given size and notifies the provided
218 * CopyStreamListener of the progress of the copy operation by calling
219 * its bytesTransferred(long, int) method after each write to the
220 * destination. If you wish to notify more than one listener you should
221 * use a CopyStreamAdapter as the listener and register the additional
222 * listeners with the CopyStreamAdapter.
223 * <p>
224 * The contents of the Reader are
225 * read until its end is reached, but neither the source nor the
226 * destination are closed. You must do this yourself outside of the
227 * method call. The number of characters read/written is returned.
228 * <p>
229 * @param source The source Reader.
230 * @param dest The destination writer.
231 * @param bufferSize The number of characters to buffer during the copy.
232 * @param streamSize The number of characters in the stream being copied.
233 * Should be set to CopyStreamEvent.UNKNOWN_STREAM_SIZE if unknown.
234 * @param listener The CopyStreamListener to notify of progress. If
235 * this parameter is null, notification is not attempted.
236 * @return The number of characters read/written in the copy operation.
237 * @exception CopyStreamException If an error occurs while reading from the
238 * source or writing to the destination. The CopyStreamException
239 * will contain the number of bytes confirmed to have been
240 * transferred before an
241 * IOException occurred, and it will also contain the IOException
242 * that caused the error. These values can be retrieved with
243 * the CopyStreamException getTotalBytesTransferred() and
244 * getIOException() methods.
245 ***/
246 public static final long copyReader(Reader source, Writer dest,
247 int bufferSize, long streamSize,
248 CopyStreamListener listener)
249 throws CopyStreamException
250 {
251 int chars;
252 long total;
253 char[] buffer;
254
255 buffer = new char[bufferSize];
256 total = 0;
257
258 try
259 {
260 while ((chars = source.read(buffer)) != -1)
261 {
262
263
264 if (chars == 0)
265 {
266 chars = source.read();
267 if (chars < 0)
268 break;
269 dest.write(chars);
270 dest.flush();
271 ++total;
272 if (listener != null)
273 listener.bytesTransferred(total, chars, streamSize);
274 continue;
275 }
276
277 dest.write(buffer, 0, chars);
278 dest.flush();
279 total += chars;
280 if (listener != null)
281 listener.bytesTransferred(total, chars, streamSize);
282 }
283 }
284 catch (IOException e)
285 {
286 throw new CopyStreamException("IOException caught while copying.",
287 total, e);
288 }
289
290 return total;
291 }
292
293
294 /***
295 * Copies the contents of a Reader to a Writer using a
296 * copy buffer of a given size. The contents of the Reader are
297 * read until its end is reached, but neither the source nor the
298 * destination are closed. You must do this yourself outside of the
299 * method call. The number of characters read/written is returned.
300 * <p>
301 * @param source The source Reader.
302 * @param dest The destination writer.
303 * @param bufferSize The number of characters to buffer during the copy.
304 * @return The number of characters read/written in the copy operation.
305 * @exception CopyStreamException If an error occurs while reading from the
306 * source or writing to the destination. The CopyStreamException
307 * will contain the number of bytes confirmed to have been
308 * transferred before an
309 * IOException occurred, and it will also contain the IOException
310 * that caused the error. These values can be retrieved with
311 * the CopyStreamException getTotalBytesTransferred() and
312 * getIOException() methods.
313 ***/
314 public static final long copyReader(Reader source, Writer dest,
315 int bufferSize)
316 throws CopyStreamException
317 {
318 return copyReader(source, dest, bufferSize,
319 CopyStreamEvent.UNKNOWN_STREAM_SIZE, null);
320 }
321
322
323 /***
324 * Same as <code> copyReader(source, dest, DEFAULT_COPY_BUFFER_SIZE); </code>
325 ***/
326 public static final long copyReader(Reader source, Writer dest)
327 throws CopyStreamException
328 {
329 return copyReader(source, dest, DEFAULT_COPY_BUFFER_SIZE);
330 }
331
332 }