diff --git a/src/main/java/htsjdk/tribble/index/AbstractIndex.java b/src/main/java/htsjdk/tribble/index/AbstractIndex.java index 42bce732d..47e31ccef 100644 --- a/src/main/java/htsjdk/tribble/index/AbstractIndex.java +++ b/src/main/java/htsjdk/tribble/index/AbstractIndex.java @@ -343,13 +343,16 @@ public void write(final LittleEndianOutputStream stream) throws IOException { } @Override + public void write(final File idxFile) throws IOException { + try(final LittleEndianOutputStream idxStream = new LittleEndianOutputStream(new BufferedOutputStream(new FileOutputStream(idxFile)))) { + write(idxStream); + } + } + + @Override public void writeBasedOnFeatureFile(final File featureFile) throws IOException { if (!featureFile.isFile()) return; - final LittleEndianOutputStream idxStream = - new LittleEndianOutputStream(new BufferedOutputStream(new FileOutputStream(Tribble.indexFile(featureFile)))); - write(idxStream); - idxStream.close(); - + write(Tribble.indexFile(featureFile)); } public void read(final LittleEndianInputStream dis) throws IOException { diff --git a/src/main/java/htsjdk/tribble/index/Index.java b/src/main/java/htsjdk/tribble/index/Index.java index 252bc95e5..ca6cc60d3 100644 --- a/src/main/java/htsjdk/tribble/index/Index.java +++ b/src/main/java/htsjdk/tribble/index/Index.java @@ -70,6 +70,14 @@ public void write(LittleEndianOutputStream stream) throws IOException; /** + * Writes the index into a file. + * + * @param idxFile Where to write the index. + * @throws IOException if the index is unable to write to the specified file + */ + public void write(final File idxFile) throws IOException; + + /** * Write an appropriately named and located Index file based on the name and location of the featureFile. * If featureFile is not a normal file, the index will silently not be written. * @param featureFile diff --git a/src/main/java/htsjdk/tribble/index/IndexFactory.java b/src/main/java/htsjdk/tribble/index/IndexFactory.java index a588220dc..3cd1b7958 100644 --- a/src/main/java/htsjdk/tribble/index/IndexFactory.java +++ b/src/main/java/htsjdk/tribble/index/IndexFactory.java @@ -41,16 +41,13 @@ import htsjdk.tribble.index.tabix.TabixIndexCreator; import htsjdk.tribble.readers.PositionalBufferedStream; import htsjdk.tribble.util.LittleEndianInputStream; -import htsjdk.tribble.util.LittleEndianOutputStream; import htsjdk.tribble.util.ParsingUtils; import htsjdk.tribble.util.TabixUtils; import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; -import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Constructor; @@ -288,18 +285,11 @@ public static LinearIndex createLinearIndex(final File inputFile, final FeatureC * @param idx * @param idxFile * @throws IOException + * @deprecated use {@link Index#write(File)} instead */ + @Deprecated public static void writeIndex(final Index idx, final File idxFile) throws IOException { - LittleEndianOutputStream stream = null; - try { - stream = new LittleEndianOutputStream(new BufferedOutputStream(new FileOutputStream(idxFile))); - idx.write(stream); - } - finally { - if(stream != null) { - stream.close(); - } - } + idx.write(idxFile); } /** diff --git a/src/main/java/htsjdk/tribble/index/tabix/TabixIndex.java b/src/main/java/htsjdk/tribble/index/tabix/TabixIndex.java index 9ab05d42e..044cefe61 100644 --- a/src/main/java/htsjdk/tribble/index/tabix/TabixIndex.java +++ b/src/main/java/htsjdk/tribble/index/tabix/TabixIndex.java @@ -201,13 +201,10 @@ public TabixFormat getFormatSpec() { * * @param tabixFile Where to write the index. */ - public void write(final File tabixFile) { - final LittleEndianOutputStream los = new LittleEndianOutputStream(new BlockCompressedOutputStream(tabixFile)); - try { + @Override + public void write(final File tabixFile) throws IOException { + try(final LittleEndianOutputStream los = new LittleEndianOutputStream(new BlockCompressedOutputStream(tabixFile))) { write(los); - los.close(); - } catch (final IOException e) { - throw new TribbleException("Exception writing " + tabixFile.getAbsolutePath(), e); } } diff --git a/src/test/java/htsjdk/tribble/FeatureReaderTest.java b/src/test/java/htsjdk/tribble/FeatureReaderTest.java index ac3405939..d62693c19 100644 --- a/src/test/java/htsjdk/tribble/FeatureReaderTest.java +++ b/src/test/java/htsjdk/tribble/FeatureReaderTest.java @@ -134,7 +134,7 @@ public void testBedNames(final File featureFile, final IndexFactory.IndexType in idxFile.delete(); } final Index idx = IndexFactory.createIndex(featureFile, codec, indexType); - IndexFactory.writeIndex(idx, idxFile); + idx.write(idxFile); idxFile.deleteOnExit(); } // else let's just hope the index exists, and if so use it diff --git a/src/test/java/htsjdk/tribble/index/IndexFactoryTest.java b/src/test/java/htsjdk/tribble/index/IndexFactoryTest.java index ba64998d3..016049f32 100644 --- a/src/test/java/htsjdk/tribble/index/IndexFactoryTest.java +++ b/src/test/java/htsjdk/tribble/index/IndexFactoryTest.java @@ -25,11 +25,14 @@ import htsjdk.samtools.SAMSequenceDictionary; import htsjdk.samtools.SAMSequenceRecord; +import htsjdk.samtools.util.IOUtil; import htsjdk.tribble.TestUtils; import htsjdk.tribble.TribbleException; import htsjdk.tribble.bed.BEDCodec; +import htsjdk.tribble.index.linear.LinearIndex; import htsjdk.tribble.index.tabix.TabixFormat; import htsjdk.tribble.index.tabix.TabixIndex; +import htsjdk.tribble.util.LittleEndianOutputStream; import htsjdk.variant.vcf.VCFCodec; import htsjdk.variant.vcf.VCFFileReader; import org.testng.Assert; @@ -37,6 +40,8 @@ import org.testng.annotations.Test; import java.io.File; +import java.io.IOException; +import java.io.OutputStream; import java.util.List; /** diff --git a/src/test/java/htsjdk/tribble/index/IndexTest.java b/src/test/java/htsjdk/tribble/index/IndexTest.java index 8104a0803..aa179a9a2 100644 --- a/src/test/java/htsjdk/tribble/index/IndexTest.java +++ b/src/test/java/htsjdk/tribble/index/IndexTest.java @@ -1,13 +1,23 @@ package htsjdk.tribble.index; +import htsjdk.samtools.util.IOUtil; +import htsjdk.tribble.FeatureCodec; import htsjdk.tribble.TestUtils; +import htsjdk.tribble.Tribble; +import htsjdk.tribble.bed.BEDCodec; import htsjdk.tribble.index.linear.LinearIndex; +import htsjdk.tribble.index.tabix.TabixFormat; +import htsjdk.tribble.index.tabix.TabixIndex; +import htsjdk.tribble.util.LittleEndianOutputStream; +import htsjdk.tribble.util.TabixUtils; +import htsjdk.variant.vcf.VCFCodec; import org.testng.Assert; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import java.io.File; import java.io.IOException; +import java.io.OutputStream; import java.util.ArrayList; import java.util.List; @@ -47,4 +57,41 @@ public void testMassiveQuery(final int start, final int mid, final int mid2, fin Assert.assertTrue(allSize >= Math.max(leftSize,rightSize), "Expected size of joint query " + allSize + " to be at least >= max of left " + leftSize + " and right queries " + rightSize); } + + + @DataProvider(name = "writeIndexData") + public Object[][] writeIndexData() { + return new Object[][]{ + {new File("src/test/resources/htsjdk/tribble/tabix/testTabixIndex.vcf"), IndexFactory.IndexType.LINEAR, new VCFCodec()}, + {new File("src/test/resources/htsjdk/tribble/tabix/testTabixIndex.vcf.gz"), IndexFactory.IndexType.TABIX, new VCFCodec()}, + {new File("src/test/resources/htsjdk/tribble/test.bed"), IndexFactory.IndexType.LINEAR, new BEDCodec()} + }; + } + + private final static OutputStream nullOutputStrem = new OutputStream() { + @Override + public void write(int b) throws IOException { } + }; + + @Test(dataProvider = "writeIndexData") + public void testWriteIndex(final File inputFile, final IndexFactory.IndexType type, final FeatureCodec codec) throws Exception { + // temp index file for this test + final File tempIndex = File.createTempFile("index", (type == IndexFactory.IndexType.TABIX) ? TabixUtils.STANDARD_INDEX_EXTENSION : Tribble.STANDARD_INDEX_EXTENSION); + tempIndex.delete(); + tempIndex.deleteOnExit(); + // create the index + final Index index = IndexFactory.createIndex(inputFile, codec, type); + Assert.assertFalse(tempIndex.exists()); + // write the index to a file + index.write(tempIndex); + Assert.assertTrue(tempIndex.exists()); + // load the generated index + final Index loadedIndex = IndexFactory.loadIndex(tempIndex.getAbsolutePath()); + // tess that the sequences and properties are the same + Assert.assertEquals(loadedIndex.getSequenceNames(), index.getSequenceNames()); + Assert.assertEquals(loadedIndex.getProperties(), index.getProperties()); + // test that write to a stream does not blows ip + index.write(new LittleEndianOutputStream(nullOutputStrem)); + } + } diff --git a/src/test/java/htsjdk/tribble/index/tabix/TabixIndexTest.java b/src/test/java/htsjdk/tribble/index/tabix/TabixIndexTest.java index 557a3987d..6981b8751 100644 --- a/src/test/java/htsjdk/tribble/index/tabix/TabixIndexTest.java +++ b/src/test/java/htsjdk/tribble/index/tabix/TabixIndexTest.java @@ -37,6 +37,7 @@ import org.testng.annotations.Test; import java.io.File; +import java.io.IOException; import java.util.Iterator; public class TabixIndexTest { @@ -71,7 +72,7 @@ public void readWriteTest(final File tabixFile) throws Exception { } @Test - public void testQueryProvidedItemsAmount() { + public void testQueryProvidedItemsAmount() throws IOException { final String VCF = "src/test/resources/htsjdk/tribble/tabix/YRI.trio.2010_07.indel.sites.vcf"; // Note that we store only compressed files final File plainTextVcfInputFile = new File(VCF);