diff --git a/jhdf/src/main/java/io/jhdf/HdfFile.java b/jhdf/src/main/java/io/jhdf/HdfFile.java index aee365dd..d6953d33 100644 --- a/jhdf/src/main/java/io/jhdf/HdfFile.java +++ b/jhdf/src/main/java/io/jhdf/HdfFile.java @@ -36,10 +36,8 @@ import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import java.nio.file.FileSystems; -import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; -import java.nio.file.StandardCopyOption; import java.nio.file.StandardOpenOption; import java.util.HashSet; import java.util.Iterator; @@ -156,7 +154,7 @@ private HdfFile(HdfBackingStorage hdfBackingStorage) { /** * Opens an {@link HdfFile} from an {@link InputStream}. The stream will be read fully into a temporary file. The - * file will be cleaned up at application exit. + * file will be deleted when the HdfFile is closed, or at application exit if it was never closed. * * @param inputStream the {@link InputStream} to read * @return HdfFile instance @@ -164,16 +162,7 @@ private HdfFile(HdfBackingStorage hdfBackingStorage) { * @see HdfFile#fromByteBuffer(ByteBuffer) */ public static HdfFile fromInputStream(InputStream inputStream) { - try { - Path tempFile = Files.createTempFile(null, "-stream.hdf5"); // null random file name - logger.info("Creating temp file [{}]", tempFile.toAbsolutePath()); - tempFile.toFile().deleteOnExit(); // Auto cleanup - Files.copy(inputStream, tempFile, StandardCopyOption.REPLACE_EXISTING); - logger.debug("Read stream to temp file [{}]", tempFile.toAbsolutePath()); - return new HdfFile(tempFile); - } catch (IOException e) { - throw new HdfException("Failed to open input stream", e); - } + return TempHdfFile.fromInputStream(inputStream); } public HdfFile(Path hdfFile) { diff --git a/jhdf/src/main/java/io/jhdf/TempHdfFile.java b/jhdf/src/main/java/io/jhdf/TempHdfFile.java new file mode 100644 index 00000000..1a6f2210 --- /dev/null +++ b/jhdf/src/main/java/io/jhdf/TempHdfFile.java @@ -0,0 +1,42 @@ +package io.jhdf; + +import io.jhdf.exceptions.HdfException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardCopyOption; + +class TempHdfFile extends HdfFile { + private static final Logger logger = LoggerFactory.getLogger(TempHdfFile.class); + + private TempHdfFile(Path tempFile) { + super(tempFile); + } + + @Override + public void close() { + super.close(); + logger.info("Deleting temp file on close [{}]", getFileAsPath().toAbsolutePath()); + boolean deleteSuccess = getFile().delete(); + if (!deleteSuccess) { + logger.warn("Could not delete temp file [{}]", getFileAsPath().toAbsolutePath()); + } + } + + public static TempHdfFile fromInputStream(InputStream inputStream) { + try { + Path tempFile = Files.createTempFile(null, "-stream.hdf5"); // null random file name + logger.info("Creating temp file [{}]", tempFile.toAbsolutePath()); + tempFile.toFile().deleteOnExit(); // Auto cleanup in case close() is never called + Files.copy(inputStream, tempFile, StandardCopyOption.REPLACE_EXISTING); + logger.debug("Read stream to temp file [{}]", tempFile.toAbsolutePath()); + return new TempHdfFile(tempFile); + } catch (IOException e) { + throw new HdfException("Failed to open input stream", e); + } + } +} diff --git a/jhdf/src/test/java/io/jhdf/HdfFileTest.java b/jhdf/src/test/java/io/jhdf/HdfFileTest.java index fd628f2b..4c45425e 100644 --- a/jhdf/src/test/java/io/jhdf/HdfFileTest.java +++ b/jhdf/src/test/java/io/jhdf/HdfFileTest.java @@ -47,8 +47,7 @@ import static org.hamcrest.Matchers.nullValue; import static org.hamcrest.Matchers.sameInstance; import static org.hamcrest.Matchers.startsWith; -import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; -import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.*; class HdfFileTest { @@ -316,6 +315,17 @@ void testReadingFromStreamThrowsWhenStreamCantBeRead() throws IOException { } } + @Test + void testReadingFromStreamDeletesTempFileOnClose() throws IOException { + File tempFile; + try (InputStream inputStream = this.getClass().getResource(HDF5_TEST_FILE_PATH).openStream(); + HdfFile hdfFile = HdfFile.fromInputStream(inputStream)) { + tempFile = hdfFile.getFile(); + assertTrue(tempFile.exists()); + } + assertFalse(tempFile.exists()); + } + @Test void testLoadingInMemoryFile() throws IOException, URISyntaxException { Path path = Paths.get(this.getClass().getResource(HDF5_TEST_FILE_PATH).toURI());