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