aboutsummaryrefslogtreecommitdiff
path: root/src/org/tukaani/xz/XZOutputStream.java
diff options
context:
space:
mode:
authorLasse Collin <lasse.collin@tukaani.org>2011-08-16 17:45:48 +0300
committerLasse Collin <lasse.collin@tukaani.org>2011-08-16 17:45:48 +0300
commit91731d444f7e210e44aa1f80d3401337016fbe13 (patch)
treea70f9e0214885680f7951ffd1906336aa0a2a486 /src/org/tukaani/xz/XZOutputStream.java
parent7dee7976d6df71942556d74083d566ca328c4e10 (diff)
downloadxz-java-91731d444f7e210e44aa1f80d3401337016fbe13.tar.gz
Small fixes to output streams.
All output streams: - Improve error handling. XZOutputStream: - Rename flushBlock to endBlock, and document that endBlock doesn't flush. - Remove setBlockFlushing.
Diffstat (limited to 'src/org/tukaani/xz/XZOutputStream.java')
-rw-r--r--src/org/tukaani/xz/XZOutputStream.java161
1 files changed, 80 insertions, 81 deletions
diff --git a/src/org/tukaani/xz/XZOutputStream.java b/src/org/tukaani/xz/XZOutputStream.java
index b14142e..77454fe 100644
--- a/src/org/tukaani/xz/XZOutputStream.java
+++ b/src/org/tukaani/xz/XZOutputStream.java
@@ -54,9 +54,9 @@ import org.tukaani.xz.index.IndexEncoder;
*/
public class XZOutputStream extends FinishableOutputStream {
private OutputStream out;
- private StreamFlags streamFlags = new StreamFlags();
- private Check check;
- private IndexEncoder index = new IndexEncoder();
+ private final StreamFlags streamFlags = new StreamFlags();
+ private final Check check;
+ private final IndexEncoder index = new IndexEncoder();
private BlockOutputStream blockEncoder = null;
private FilterEncoder[] filters;
@@ -68,12 +68,6 @@ public class XZOutputStream extends FinishableOutputStream {
*/
private boolean filtersSupportFlushing;
- /**
- * True if <code>flush()</code> should use <code>flushBlock()</code>
- * even if the filter chain does support flushing.
- */
- private boolean alwaysFlushBlock = false;
-
private IOException exception = null;
private boolean finished = false;
@@ -274,14 +268,11 @@ public class XZOutputStream extends FinishableOutputStream {
if (off < 0 || len < 0 || off + len < 0 || off + len > buf.length)
throw new IndexOutOfBoundsException();
- if (len == 0)
- return;
-
if (exception != null)
throw exception;
if (finished)
- throw new XZIOException("Cannot write to a finished stream");
+ throw new XZIOException("Stream finished or closed");
try {
if (blockEncoder == null)
@@ -295,13 +286,40 @@ public class XZOutputStream extends FinishableOutputStream {
}
/**
- * Finishes the current XZ Block. This is a helper for flushBlock()
- * and finish().
+ * Finishes the current XZ Block (but not the whole XZ Stream).
+ * This doesn't flush the stream so it's possible that not all data will
+ * be decompressible from the output stream when this function returns.
+ * Call also <code>flush()</code> if flushing is wanted in addition to
+ * finishing the current XZ Block.
+ * <p>
+ * If there is no unfinished Block open, this function will do nothing.
+ * (No empty XZ Block will be created.)
+ * <p>
+ * This function can be useful, for example, to create
+ * random-accessible .xz files.
+ * <p>
+ * Starting a new XZ Block means that the encoder state is reset.
+ * Doing this very often will increase the size of the compressed
+ * file a lot (more than plain <code>flush()</code> would do).
+ *
+ * @throws XZIOException
+ * XZ Stream has grown too big
+ *
+ * @throws XZIOException
+ * stream finished or closed
+ *
+ * @throws IOException may be thrown by the underlying output stream
*/
- private void endBlock() throws IOException {
+ public void endBlock() throws IOException {
if (exception != null)
throw exception;
+ if (finished)
+ throw new XZIOException("Stream finished or closed");
+
+ // NOTE: Once there is threading with multiple Blocks, it's possible
+ // that this function will be more like a barrier that returns
+ // before the last Block has been finished.
if (blockEncoder != null) {
try {
blockEncoder.finish();
@@ -316,29 +334,6 @@ public class XZOutputStream extends FinishableOutputStream {
}
/**
- * Finishes the current XZ Block (but not the whole XZ Stream) and
- * calls <code>out.flush()</code>.
- * All buffered pending data will then be decompressible from
- * the output stream. If there is no unfinished Block open,
- * no empty Block will be created.
- * <p>
- * <code>flushBlock()</code> resets the encoder state so there will be
- * a bigger penalty in compressed file size than with <code>flush()</code>.
- * <p>
- * <code>flushBlock()</code> can be useful, for example, to create
- * random-accessible .xz files.
- *
- * @throws XZIOException
- * XZ Stream has grown too big
- *
- * @throws IOException may be thrown by the underlying output stream
- */
- public void flushBlock() throws IOException {
- endBlock();
- out.flush();
- }
-
- /**
* Flushes the encoder and calls <code>out.flush()</code>.
* All buffered pending data will then be decompressible from
* the output stream.
@@ -349,45 +344,41 @@ public class XZOutputStream extends FinishableOutputStream {
* smaller penalty with flushing than BT4.
* <p>
* Some filters don't support flushing. If the filter chain has
- * such a filter, <code>flush()</code> is equivalent to
- * <code>flushBlock()</code>.
- * <p>
- * If <code>setBlockFlushing(true)</code> has been used,
- * <code>flush()</code> is equivalent to <code>flushBlock()</code>
- * even if the filter chain does support flushing.
+ * such a filter, <code>flush()</code> will call <code>endBlock()</code>
+ * before flushing.
*
* @throws XZIOException
* XZ Stream has grown too big
*
+ * @throws XZIOException
+ * stream finished or closed
+ *
* @throws IOException may be thrown by the underlying output stream
*/
public void flush() throws IOException {
if (exception != null)
throw exception;
- if (!filtersSupportFlushing || alwaysFlushBlock)
- flushBlock();
- else if (blockEncoder != null)
- blockEncoder.flush(); // This also calls out.flush().
- else
- out.flush();
- }
+ if (finished)
+ throw new XZIOException("Stream finished or closed");
- /**
- * Sets the default flushing mode for <code>flush()</code>.
- * <p>
- * Calling <code>setBlockFlushing(true)</code> will make
- * <code>flush()</code> equivalent to <code>flushBlock()</code>
- * even with filter chains that support flushing. Calling
- * <code>setBlockFlushing(false)</code> will restore the default
- * behavior.
- * <p>
- * This function is rarely useful. Normally you should use
- * <code>flushBlock()</code> directly if you want to start
- * a new XZ Block.
- */
- public void setBlockFlushing(boolean flushFlushesBlock) {
- alwaysFlushBlock = flushFlushesBlock;
+ try {
+ if (blockEncoder != null) {
+ if (filtersSupportFlushing) {
+ // This will eventually call out.flush() so
+ // no need to do it here again.
+ blockEncoder.flush();
+ } else {
+ endBlock();
+ out.flush();
+ }
+ } else {
+ out.flush();
+ }
+ } catch (IOException e) {
+ exception = e;
+ throw e;
+ }
}
/**
@@ -417,11 +408,15 @@ public class XZOutputStream extends FinishableOutputStream {
try {
index.encode(out);
encodeStreamFooter();
- finished = true;
} catch (IOException e) {
exception = e;
throw e;
}
+
+ // Set it to true only if everything goes fine. Setting it earlier
+ // would cause repeated calls to finish() do nothing instead of
+ // throwing an exception to indicate an earlier error.
+ finished = true;
}
}
@@ -438,20 +433,24 @@ public class XZOutputStream extends FinishableOutputStream {
* @throws IOException may be thrown by the underlying output stream
*/
public void close() throws IOException {
- // If finish() throws an exception, it stores the exception to
- // the variable "exception". So we can ignore the possible
- // exception here.
- try {
- finish();
- } catch (IOException e) {}
+ if (out != null) {
+ // If finish() throws an exception, it stores the exception to
+ // the variable "exception". So we can ignore the possible
+ // exception here.
+ try {
+ finish();
+ } catch (IOException e) {}
- try {
- out.close();
- } catch (IOException e) {
- // Remember the exception but only if there is no previous
- // pending exception.
- if (exception == null)
- exception = e;
+ try {
+ out.close();
+ } catch (IOException e) {
+ // Remember the exception but only if there is no previous
+ // pending exception.
+ if (exception == null)
+ exception = e;
+ }
+
+ out = null;
}
if (exception != null)