Add 'src/be/nikiroo/utils/' from commit '46add0670fdee4bd936a13fe2448c5e20a7ffd0a'
[fanfix.git] / src / be / nikiroo / utils / streams / BufferedOutputStream.java
index 6f600eba7c06384db6f254ed8a89642257641156..14425345c179196d8944d3c391b60393c28db9d5 100644 (file)
@@ -22,12 +22,22 @@ public class BufferedOutputStream extends OutputStream {
        protected byte[] buffer;
        /** An End-Of-File (or buffer, here) marker. */
        protected boolean eof;
+       /** The actual under-laying stream. */
+       protected OutputStream out;
+       /** The number of bytes written to the under-laying stream. */
+       protected long bytesWritten;
+       /**
+        * Can bypass the flush process for big writes (will directly write to the
+        * under-laying buffer if the array to write is > the internal buffer
+        * size).
+        * <p>
+        * By default, this is true.
+        */
+       protected boolean bypassFlush = true;
 
        private boolean closed;
-       private OutputStream out;
        private int openCounter;
-
-       private long bytesWritten;
+       private byte[] b1;
 
        /**
         * Create a new {@link BufferedInputStream} that wraps the given
@@ -40,19 +50,15 @@ public class BufferedOutputStream extends OutputStream {
                this.out = out;
 
                this.buffer = new byte[4096];
+               this.b1 = new byte[1];
                this.start = 0;
                this.stop = 0;
        }
 
        @Override
        public void write(int b) throws IOException {
-               checkClose();
-
-               if (available() <= 0) {
-                       flush(false);
-               }
-
-               buffer[start++] = (byte) b;
+               b1[0] = (byte) b;
+               write(b1, 0, 1);
        }
 
        @Override
@@ -77,7 +83,7 @@ public class BufferedOutputStream extends OutputStream {
                        return;
                }
 
-               if (sourceLength >= buffer.length) {
+               if (bypassFlush && sourceLength >= buffer.length) {
                        /*
                         * If the request length exceeds the size of the output buffer,
                         * flush the output buffer and then write the data directly. In this
@@ -85,6 +91,7 @@ public class BufferedOutputStream extends OutputStream {
                         */
                        flush(false);
                        out.write(source, sourceOffset, sourceLength);
+                       bytesWritten += (sourceLength - sourceOffset);
                        return;
                }
 
@@ -94,7 +101,7 @@ public class BufferedOutputStream extends OutputStream {
                                flush(false);
                        }
 
-                       int now = Math.min(sourceLength, available());
+                       int now = Math.min(sourceLength - done, available());
                        System.arraycopy(source, sourceOffset + done, buffer, stop, now);
                        stop += now;
                        done += now;
@@ -165,19 +172,30 @@ public class BufferedOutputStream extends OutputStream {
        }
 
        /**
-        * Flush the {@link BufferedOutputStream}, and optionally the under-laying
-        * stream, too.
+        * Flush the {@link BufferedOutputStream}, write the current buffered data
+        * to (and optionally also flush) the under-laying stream.
+        * <p>
+        * If {@link BufferedOutputStream#bypassFlush} is false, all writes to the
+        * under-laying stream are done in this method.
+        * <p>
+        * This can be used if you want to write some data in the under-laying
+        * stream yourself (in that case, flush this {@link BufferedOutputStream}
+        * with or without flushing the under-laying stream, then you can write to
+        * the under-laying stream).
         * 
         * @param includingSubStream
         *            also flush the under-laying stream
         * @throws IOException
         *             in case of I/O error
         */
-       private void flush(boolean includingSubStream) throws IOException {
-               out.write(buffer, start, stop - start);
-               bytesWritten += (stop - start);
+       public void flush(boolean includingSubStream) throws IOException {
+               if (stop > start) {
+                       out.write(buffer, start, stop - start);
+                       bytesWritten += (stop - start);
+               }
                start = 0;
                stop = 0;
+
                if (includingSubStream) {
                        out.flush();
                }
@@ -232,7 +250,7 @@ public class BufferedOutputStream extends OutputStream {
                                openCounter--;
                        } else {
                                closed = true;
-                               flush(true);
+                               flush(includingSubStream);
                                if (includingSubStream && out != null) {
                                        out.close();
                                }