Hi,

A bit of background.. org.apache.avalon.excalibur.io.IOUtil has a method which
copies from an InputStream to an OutputStream:

public static void copy( final InputStream source, final OutputStream destination ) 
throws IOException;

I've been using this to write a stream to System.out for debugging purposes:

InputStream in = new FileInputStream("foo.xml");
org.apache.avalon.excalibur.io.IOUtil.copy(in, System.out);


After much painful debugging, I've discovered that copy() flushes and closes
both streams before exiting. This is certainly not the desired effect for
System.out!

I'd suggest that, as a rule, it is the caller's responsibility to flush and
close streams, not the called method. System.out is a good example of why
methods shouldn't close streams they get passed. Same for flushing; it should
be the caller's responsibility. What happens if my OutputStream was obtained
from response.getOutputStream(), and I only want to flush right at the end (or
my servlet breaks)? Likewise, copy() should not try to wrap the streams in a
Buffered*Stream, as that necessitates a flush, which may not be what the caller
wants/expects.

In short, methods, especially in utility code like excalibur, should be
side-effect-free, doing *only* what they advertise.

</rant> ;)

Anyway, patch is attached. I've also added a bufferedCopy() method for those
who do want buffered/flushed io.


--Jeff
Index: src/java/org/apache/avalon/excalibur/io/IOUtil.java
===================================================================
RCS file: 
/home/cvspublic/jakarta-avalon/src/java/org/apache/avalon/excalibur/io/IOUtil.java,v
retrieving revision 1.1
diff -u -r1.1 IOUtil.java
--- src/java/org/apache/avalon/excalibur/io/IOUtil.java 2001/04/26 14:16:11     1.1
+++ src/java/org/apache/avalon/excalibur/io/IOUtil.java 2001/05/29 05:36:23
@@ -40,35 +40,40 @@
     }
 
     /**
-     * Copy stream-data from source to destination.
+     * Copy stream-data from source to destination. This method does not
+     * buffer, flush or close the streams, as to do so would require making
+     * non-portable assumptions about the streams' origin and further use. If
+     * you wish to perform a buffered copy, use {@link #bufferedCopy}.
      */
     public static void copy( final InputStream source, final OutputStream destination 
)
         throws IOException
     {
-        try
-        {
-            final BufferedInputStream input = new BufferedInputStream( source );
-            final BufferedOutputStream output = new BufferedOutputStream( destination 
);
-
-            final int BUFFER_SIZE = 1024 * 4;
-            final byte[] buffer = new byte[ BUFFER_SIZE ];
-
-            while( true )
-            {
-                final int count = input.read( buffer, 0, BUFFER_SIZE );
-                if( -1 == count ) break;
+        final int BUFFER_SIZE = 1024 * 4;
+        final byte[] buffer = new byte[ BUFFER_SIZE ];
 
-                // write out those same bytes
-                output.write( buffer, 0, count );
-            }
-
-            //needed to flush cache
-            output.flush();
-        }
-        finally
+        while( true )
         {
-            shutdownStream( source );
-            shutdownStream( destination );
+            final int count = source.read( buffer, 0, BUFFER_SIZE );
+            if( -1 == count ) break;
+
+            // write out those same bytes
+            destination.write( buffer, 0, count );
         }
+    }
+
+    /**
+     * Copy stream-data from source to destination, with buffering.
+     * This is equivalent to passing {@link #copy} a {@link
+     * java.io.BufferedInputStream} and {@link java.io.BufferedOuputStream} to
+     * {@link #copy}, and flushing the output stream afterwards. The streams
+     * are not closed after the copy.
+     */
+    public static void bufferedCopy( final InputStream source, final OutputStream 
+destination )
+        throws IOException
+    {
+        final BufferedInputStream input = new BufferedInputStream( source );
+        final BufferedOutputStream output = new BufferedOutputStream( destination );
+        copy(input, output);
+        output.flush();
     }
 }

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to