001 /* 002 * Copyright 2001-2005 The Apache Software Foundation 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 package org.apache.commons.net.io; 017 018 import java.io.IOException; 019 import java.io.InputStream; 020 import java.io.OutputStream; 021 import java.io.Reader; 022 import java.io.Writer; 023 024 /*** 025 * The Util class cannot be instantiated and stores short static convenience 026 * methods that are often quite useful. 027 * <p> 028 * <p> 029 * @see CopyStreamException 030 * @see CopyStreamListener 031 * @see CopyStreamAdapter 032 * @author Daniel F. Savarese 033 ***/ 034 035 public final class Util 036 { 037 /*** 038 * The default buffer size used by {@link #copyStream copyStream } 039 * and {@link #copyReader copyReader }. It's value is 1024. 040 ***/ 041 public static final int DEFAULT_COPY_BUFFER_SIZE = 1024; 042 043 // Cannot be instantiated 044 private Util() 045 { } 046 047 048 /*** 049 * Copies the contents of an InputStream to an OutputStream using a 050 * copy buffer of a given size and notifies the provided 051 * CopyStreamListener of the progress of the copy operation by calling 052 * its bytesTransferred(long, int) method after each write to the 053 * destination. If you wish to notify more than one listener you should 054 * use a CopyStreamAdapter as the listener and register the additional 055 * listeners with the CopyStreamAdapter. 056 * <p> 057 * The contents of the InputStream are 058 * read until the end of the stream is reached, but neither the 059 * source nor the destination are closed. You must do this yourself 060 * outside of the method call. The number of bytes read/written is 061 * returned. 062 * <p> 063 * @param source The source InputStream. 064 * @param dest The destination OutputStream. 065 * @param bufferSize The number of bytes to buffer during the copy. 066 * @param streamSize The number of bytes in the stream being copied. 067 * Should be set to CopyStreamEvent.UNKNOWN_STREAM_SIZE if unknown. 068 * @param listener The CopyStreamListener to notify of progress. If 069 * this parameter is null, notification is not attempted. 070 * @param flush Whether to flush the output stream after every 071 * write. This is necessary for interactive sessions that rely on 072 * buffered streams. If you don't flush, the data will stay in 073 * the stream buffer. 074 * @exception CopyStreamException If an error occurs while reading from the 075 * source or writing to the destination. The CopyStreamException 076 * will contain the number of bytes confirmed to have been 077 * transferred before an 078 * IOException occurred, and it will also contain the IOException 079 * that caused the error. These values can be retrieved with 080 * the CopyStreamException getTotalBytesTransferred() and 081 * getIOException() methods. 082 ***/ 083 public static final long copyStream(InputStream source, OutputStream dest, 084 int bufferSize, long streamSize, 085 CopyStreamListener listener, 086 boolean flush) 087 throws CopyStreamException 088 { 089 int bytes; 090 long total; 091 byte[] buffer; 092 093 buffer = new byte[bufferSize]; 094 total = 0; 095 096 try 097 { 098 while ((bytes = source.read(buffer)) != -1) 099 { 100 // Technically, some read(byte[]) methods may return 0 and we cannot 101 // accept that as an indication of EOF. 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 // Technically, some read(char[]) methods may return 0 and we cannot 263 // accept that as an indication of EOF. 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 }