001 /*
002 * JAPI - (Yet another (hopefully) useful) Java API
003 *
004 * Copyright (C) 2006 Christian Hujer
005 *
006 * This program is free software; you can redistribute it and/or
007 * modify it under the terms of the GNU General Public License as
008 * published by the Free Software Foundation; either version 2 of the
009 * License, or (at your option) any later version.
010 *
011 * This program is distributed in the hope that it will be useful, but
012 * WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014 * General Public License for more details.
015 *
016 * You should have received a copy of the GNU General Public License
017 * along with this program; if not, write to the Free Software
018 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
019 * 02111-1307, USA.
020 */
021
022 package net.sf.japi.io;
023
024 import java.io.InputStream;
025 import java.io.OutputStream;
026 import java.io.IOException;
027
028 /** A Runnable that copies from an InputStream to an OutputStream.
029 * @author <a href="mailto:chris@riedquat.de">Christian Hujer</a>
030 */
031 public class Copier implements Runnable {
032
033 /** Default buffer size when copying. */
034 public static final int DEFAULT_BUF_SIZE = 8192;
035
036 /** Default automatic flush. */
037 public static final boolean DEFAULT_AUTO_FLUSH = true;
038
039 /** Default automatic close. */
040 public static final boolean DEFAULT_AUTO_CLOSE = true;
041
042 /** The InputStream to read from. */
043 private final InputStream in;
044
045 /** The OutputStream to write to. */
046 private final OutputStream out;
047
048 /** The buffer size to use. */
049 private final int bufSize;
050
051 /** Whether to flush automatically. */
052 private final boolean autoFlush;
053
054 /** Whether to close streams automatically after copying. */
055 private final boolean autoClose;
056
057 /** Create a Copier with default buffer size and autoFlush.
058 * @param in the InputStream to read from
059 * @param out the OutputStream to write to
060 */
061 public Copier(final InputStream in, final OutputStream out) {
062 this(in, out, DEFAULT_BUF_SIZE, DEFAULT_AUTO_FLUSH, DEFAULT_AUTO_CLOSE);
063 }
064
065 /** Create a Copier with specified buffer size and automatic flush behaviour.
066 * @param in the InputStream to read from
067 * @param out the OutputStream to write to
068 * @param bufSize buffer size to use while copying
069 */
070 public Copier(final InputStream in, final OutputStream out, final int bufSize) {
071 this(in, out, bufSize, DEFAULT_AUTO_FLUSH, DEFAULT_AUTO_CLOSE);
072 }
073
074 /** Create a Copier with specified buffer size and specified flush behaviour.
075 * @param in the InputStream to read from
076 * @param out the OutputStream to write to
077 * @param bufSize buffer size to use while copying
078 * @param autoFlush whether to flush automatically (true for automatic flush, false for flush on close)
079 * @param autoClose whether to close the streams automatically (true for automatic close, false for no close)
080 */
081 public Copier(final InputStream in, final OutputStream out, final int bufSize, final boolean autoFlush, final boolean autoClose) {
082 this.in = in;
083 this.out = out;
084 this.bufSize = bufSize;
085 this.autoFlush = autoFlush;
086 this.autoClose = autoClose;
087 }
088
089 /** Start the copier in a new thread.
090 * @return the newly created thread
091 */
092 public Thread start() {
093 final Thread thread = new Thread(this);
094 thread.start();
095 return thread;
096 }
097
098 /** {@inheritDoc} */
099 public void run() {
100 final byte[] buf = new byte[bufSize];
101 try {
102 for (int bytesRead; (bytesRead = in.read(buf)) != -1;) {
103 out.write(buf, 0, bytesRead);
104 if (autoFlush) {
105 out.flush();
106 }
107 }
108 } catch (final IOException e) {
109 System.err.println(e);
110 } finally {
111 //noinspection CatchGenericClass,OverlyBroadCatchBlock
112 try { out.flush(); } catch (final Exception ignore) { /* ignore */ }
113 if (autoClose) {
114 //noinspection CatchGenericClass,OverlyBroadCatchBlock
115 try { out.close(); } catch (final Exception ignore) { /* ignore */ }
116 //noinspection CatchGenericClass,OverlyBroadCatchBlock
117 try { in.close(); } catch (final Exception ignore) { /* ignore */ }
118 }
119 }
120 }
121
122 } // class Copier