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