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]