ee87c19c3d6100c6ec7d8856f14da97b4d5fe9f1
[jSite.git] / src / de / todesbaum / util / io / StreamCopier.java
1 /*
2  * This program is free software; you can redistribute it and/or modify it under
3  * the terms of the GNU General Public License as published by the Free Software
4  * Foundation; either version 2 of the License, or (at your option) any later
5  * version.
6  *
7  * This program is distributed in the hope that it will be useful, but WITHOUT
8  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
9  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
10  * details.
11  *
12  * You should have received a copy of the GNU General Public License along with
13  * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
14  * Place - Suite 330, Boston, MA 02111-1307, USA.
15  */
16
17 package de.todesbaum.util.io;
18
19 import java.io.EOFException;
20 import java.io.IOException;
21 import java.io.InputStream;
22 import java.io.OutputStream;
23 import java.util.EventListener;
24
25 /**
26  * Copies input from an {@link InputStream} to an {@link OutputStream}.
27  *
28  * @author <a href="mailto:droden@gmail.com">David Roden</a>
29  * @version $Id$
30  */
31 public class StreamCopier {
32
33         /**
34          * The default size of the buffer.
35          */
36         private static final int BUFFER_SIZE = 64 * 1024;
37
38         /**
39          * The {@link InputStream} to read from.
40          */
41         private InputStream inputStream;
42
43         /**
44          * The {@link OutputStream} to write to.
45          */
46         private OutputStream outputStream;
47
48         /**
49          * The number of bytes to copy.
50          */
51         private long length;
52
53         /**
54          * The size of the buffer.
55          */
56         private int bufferSize;
57
58         /**
59          * Creates a new StreamCopier with the specified parameters and the default
60          * buffer size.
61          *
62          * @param inputStream
63          *            The {@link InputStream} to read from
64          * @param outputStream
65          *            The {@link OutputStream} to write to
66          * @param length
67          *            The number of bytes to copy
68          */
69         public StreamCopier(InputStream inputStream, OutputStream outputStream, long length) {
70                 this(inputStream, outputStream, length, BUFFER_SIZE);
71         }
72
73         /**
74          * Creates a new StreamCopier with the specified parameters and the default
75          * buffer size.
76          *
77          * @param inputStream
78          *            The {@link InputStream} to read from
79          * @param outputStream
80          *            The {@link OutputStream} to write to
81          * @param length
82          *            The number of bytes to copy
83          * @param bufferSize
84          *            The number of bytes to copy at a time
85          */
86         public StreamCopier(InputStream inputStream, OutputStream outputStream, long length, int bufferSize) {
87                 this.inputStream = inputStream;
88                 this.outputStream = outputStream;
89                 this.length = length;
90                 this.bufferSize = bufferSize;
91         }
92
93         /**
94          * Copies the stream data. If the input stream is depleted before the
95          * requested number of bytes have been read an {@link EOFException} is
96          * thrown.
97          *
98          * @throws EOFException
99          *             if the input stream is depleted before the requested number
100          *             of bytes has been read
101          * @throws IOException
102          *             if an I/O error occurs
103          */
104         public void copy() throws EOFException, IOException {
105                 copy(inputStream, outputStream, length, bufferSize);
106         }
107
108         /**
109          * Copies the stream data. If the input stream is depleted before the
110          * requested number of bytes have been read an {@link EOFException} is
111          * thrown.
112          *
113          * @param progressListener
114          *            The progress listener (may be {@code null})
115          * @throws EOFException
116          *             if the input stream is depleted before the requested number
117          *             of bytes has been read
118          * @throws IOException
119          *             if an I/O error occurs
120          */
121         public void copy(ProgressListener progressListener) throws EOFException, IOException {
122                 copy(inputStream, outputStream, length, bufferSize, progressListener);
123         }
124
125         /**
126          * Copies <code>length</code> bytes from the <code>inputStream</code> to
127          * the <code>outputStream</code>.
128          *
129          * @param inputStream
130          *            The input stream to read from
131          * @param outputStream
132          *            The output stream to write to
133          * @param length
134          *            The number of bytes to copy
135          * @throws IOException
136          *             if an I/O exception occurs
137          */
138         public static void copy(InputStream inputStream, OutputStream outputStream, long length) throws IOException {
139                 copy(inputStream, outputStream, length, BUFFER_SIZE);
140         }
141
142         /**
143          * Copies <code>length</code> bytes from the <code>inputStream</code> to
144          * the <code>outputStream</code>.
145          *
146          * @param inputStream
147          *            The input stream to read from
148          * @param outputStream
149          *            The output stream to write to
150          * @param length
151          *            The number of bytes to copy
152          * @param progressListener
153          *            The progress listener (may be {@code null})
154          * @throws IOException
155          *             if an I/O exception occurs
156          */
157         public static void copy(InputStream inputStream, OutputStream outputStream, long length, ProgressListener progressListener) throws IOException {
158                 copy(inputStream, outputStream, length, BUFFER_SIZE, progressListener);
159         }
160
161         /**
162          * Copies <code>length</code> bytes from the <code>inputStream</code> to
163          * the <code>outputStream</code> using a buffer with the specified size
164          *
165          * @param inputStream
166          *            The input stream to read from
167          * @param outputStream
168          *            The output stream to write to
169          * @param length
170          *            The number of bytes to copy
171          * @param bufferSize
172          *            The size of the copy buffer
173          * @throws IOException
174          *             if an I/O exception occurs
175          */
176         public static void copy(InputStream inputStream, OutputStream outputStream, long length, int bufferSize) throws IOException {
177                 copy(inputStream, outputStream, length, bufferSize, null);
178         }
179
180         /**
181          * Copies <code>length</code> bytes from the <code>inputStream</code> to
182          * the <code>outputStream</code> using a buffer with the specified size
183          *
184          * @param inputStream
185          *            The input stream to read from
186          * @param outputStream
187          *            The output stream to write to
188          * @param length
189          *            The number of bytes to copy
190          * @param bufferSize
191          *            The size of the copy buffer
192          * @param progressListener
193          *            The progress listener (may be {@code null})
194          * @throws IOException
195          *             if an I/O exception occurs
196          */
197         public static void copy(InputStream inputStream, OutputStream outputStream, long length, int bufferSize, ProgressListener progressListener) throws IOException {
198                 long remaining = length;
199                 byte[] buffer = new byte[bufferSize];
200                 while (remaining > 0) {
201                         int read = inputStream.read(buffer, 0, (int) Math.min(Integer.MAX_VALUE, Math.min(bufferSize, remaining)));
202                         if (read == -1) {
203                                 throw new EOFException();
204                         }
205                         outputStream.write(buffer, 0, read);
206                         remaining -= read;
207                         if (progressListener != null) {
208                                 progressListener.onProgress(length - remaining, length);
209                         }
210                 }
211         }
212
213         /**
214          * Interface for objects that want to be notified about the progress of a
215          * {@link StreamCopier#copy()} operation.
216          *
217          * @author David ‘Bombe’ Roden &lt;bombe@freenetproject.org&gt;
218          */
219         public static interface ProgressListener extends EventListener {
220
221                 /**
222                  * Notifiies a listener that a copy process made some progress.
223                  *
224                  * @param copied
225                  *            The number of bytes that have already been copied
226                  * @param length
227                  *            The total number of bytes that will be copied
228                  */
229                 public void onProgress(long copied, long length);
230
231         }
232
233 }