This is an automated email from the ASF dual-hosted git repository. ggregory pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/commons-io.git
The following commit(s) were added to refs/heads/master by this push: new ddbfad9 IO-651 Add DeferredFileOutputStream.getInputStream() (#206) ddbfad9 is described below commit ddbfad9b0b11136c2908e00e22732c0bc7369e83 Author: jmark109 <79322278+jmark...@users.noreply.github.com> AuthorDate: Mon Feb 22 14:53:18 2021 -0500 IO-651 Add DeferredFileOutputStream.getInputStream() (#206) Add DeferredFileOutputStream.getInputStream() for efficient retrieval of OutputSteam data. Co-authored-by: kare1634 <kare1...@incorporatedmail.com> --- .../io/output/DeferredFileOutputStream.java | 31 +++++++++++++++ .../io/output/DeferredFileOutputStreamTest.java | 46 ++++++++++++++++++++++ 2 files changed, 77 insertions(+) diff --git a/src/main/java/org/apache/commons/io/output/DeferredFileOutputStream.java b/src/main/java/org/apache/commons/io/output/DeferredFileOutputStream.java index 25773fc..d6dac39 100644 --- a/src/main/java/org/apache/commons/io/output/DeferredFileOutputStream.java +++ b/src/main/java/org/apache/commons/io/output/DeferredFileOutputStream.java @@ -20,7 +20,9 @@ import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; +import java.io.InputStream; import java.io.OutputStream; +import java.nio.file.Files; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; @@ -272,4 +274,33 @@ public class DeferredFileOutputStream extends ThresholdingOutputStream { } } } + + /** + * Gets the current contents of this byte stream as an {@link InputStream}. + * If the data for this output stream has been retained in memory, the + * returned stream is backed by buffers of {@code this} stream, + * avoiding memory allocation and copy, thus saving space and time.<br> + * Otherwise, the returned stream will be one that is created from the data + * that has been committed to disk. + * + * @return the current contents of this output stream. + * @throws IOException if this stream is not yet closed or an error occurs. + * @see org.apache.commons.io.output.ByteArrayOutputStream#toInputStream() + * + * @since 2.9 + */ + public InputStream toInputStream() throws IOException { + // we may only need to check if this is closed if we are working with a file + // but we should force the habit of closing whether we are working with + // a file or memory. + if (!closed) { + throw new IOException("Stream not closed"); + } + + if (isInMemory()) { + return memoryOutputStream.toInputStream(); + } else { + return Files.newInputStream(outputFile.toPath()); + } + } } diff --git a/src/test/java/org/apache/commons/io/output/DeferredFileOutputStreamTest.java b/src/test/java/org/apache/commons/io/output/DeferredFileOutputStreamTest.java index f5200c1..23a1c35 100644 --- a/src/test/java/org/apache/commons/io/output/DeferredFileOutputStreamTest.java +++ b/src/test/java/org/apache/commons/io/output/DeferredFileOutputStreamTest.java @@ -16,6 +16,7 @@ */ package org.apache.commons.io.output; +import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -27,9 +28,13 @@ import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Path; import java.util.Arrays; import java.util.stream.IntStream; +import org.apache.commons.io.IOUtils; +import org.junit.jupiter.api.io.TempDir; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; @@ -365,4 +370,45 @@ public class DeferredFileOutputStreamTest { fail("Unexpected IOException"); } } + + /** + * Tests the case where the amount of data falls below the threshold, and is therefore confined to memory. + * Testing the getInputStream() method. + */ + @ParameterizedTest(name = "initialBufferSize = {0}") + @MethodSource("data") + public void testBelowThresholdGetInputStream(final int initialBufferSize) throws IOException { + final DeferredFileOutputStream dfos = new DeferredFileOutputStream(testBytes.length + 42, initialBufferSize, + null); + dfos.write(testBytes, 0, testBytes.length); + dfos.close(); + assertTrue(dfos.isInMemory()); + + try (InputStream is = dfos.toInputStream()) { + assertArrayEquals(testBytes, IOUtils.toByteArray(is)); + } + } + + /** + * Tests the case where the amount of data exceeds the threshold, and is therefore written to disk. The actual data + * written to disk is verified, as is the file itself. + * Testing the getInputStream() method. + */ + @ParameterizedTest(name = "initialBufferSize = {0}") + @MethodSource("data") + public void testAboveThresholdGetInputStream(final int initialBufferSize, final @TempDir Path tempDir) throws IOException { + final File testFile = tempDir.resolve("testAboveThreshold.dat").toFile(); + + final DeferredFileOutputStream dfos = new DeferredFileOutputStream(testBytes.length - 5, initialBufferSize, + testFile); + dfos.write(testBytes, 0, testBytes.length); + dfos.close(); + assertFalse(dfos.isInMemory()); + + try (InputStream is = dfos.toInputStream()) { + assertArrayEquals(testBytes, IOUtils.toByteArray(is)); + } + + verifyResultFile(testFile); + } }