diff --git a/src/main/java/net/lingala/zip4j/io/inputstream/NumberedSplitFileInputStream.java b/src/main/java/net/lingala/zip4j/io/inputstream/NumberedSplitFileInputStream.java new file mode 100644 index 00000000..d715e89b --- /dev/null +++ b/src/main/java/net/lingala/zip4j/io/inputstream/NumberedSplitFileInputStream.java @@ -0,0 +1,47 @@ +package net.lingala.zip4j.io.inputstream; + +import net.lingala.zip4j.model.FileHeader; +import net.lingala.zip4j.model.enums.RandomAccessFileMode; + +import java.io.File; +import java.io.IOException; +import java.io.RandomAccessFile; + +/** + * A split input stream for zip file split with 7-zip. They end with .zip.001, .zip.002, etc + */ +public class NumberedSplitFileInputStream extends SplitFileInputStream { + + private RandomAccessFile randomAccessFile; + + public NumberedSplitFileInputStream(File zipFile) throws IOException { + this.randomAccessFile = new NumberedSplitRandomAccessFile(zipFile, RandomAccessFileMode.READ.getValue()); + } + + @Override + public int read() throws IOException { + return randomAccessFile.read(); + } + + @Override + public int read(byte[] b) throws IOException { + return this.read(b,0, b.length); + } + + @Override + public int read(byte[] b, int off, int len) throws IOException { + return randomAccessFile.read(b, off, len); + } + + @Override + public void prepareExtractionForFileHeader(FileHeader fileHeader) throws IOException { + randomAccessFile.seek(fileHeader.getOffsetLocalHeader()); + } + + @Override + public void close() throws IOException { + if (randomAccessFile != null) { + randomAccessFile.close(); + } + } +} diff --git a/src/main/java/net/lingala/zip4j/io/inputstream/NumberedSplitInputStream.java b/src/main/java/net/lingala/zip4j/io/inputstream/NumberedSplitInputStream.java deleted file mode 100644 index 782a7418..00000000 --- a/src/main/java/net/lingala/zip4j/io/inputstream/NumberedSplitInputStream.java +++ /dev/null @@ -1,26 +0,0 @@ -package net.lingala.zip4j.io.inputstream; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; - -import static net.lingala.zip4j.util.FileUtils.getNextNumberedSplitFileCounterAsExtension; - -/** - * A split input stream for zip file split with 7-zip. They end with .zip.001, .zip.002, etc - */ -public class NumberedSplitInputStream extends SplitInputStream { - - public NumberedSplitInputStream(File zipFile, boolean isSplitZipArchive, int lastSplitZipFileNumber) - throws FileNotFoundException { - super(zipFile, isSplitZipArchive, lastSplitZipFileNumber); - } - - @Override - protected File getNextSplitFile(int zipFileIndex) throws IOException { - String currZipFileNameWithPath = zipFile.getCanonicalPath(); - String fileNameWithPathAndWithoutExtension = currZipFileNameWithPath.substring(0, - currZipFileNameWithPath.lastIndexOf(".")); - return new File(fileNameWithPathAndWithoutExtension + getNextNumberedSplitFileCounterAsExtension(zipFileIndex)); - } -} diff --git a/src/main/java/net/lingala/zip4j/io/inputstream/SplitFileInputStream.java b/src/main/java/net/lingala/zip4j/io/inputstream/SplitFileInputStream.java new file mode 100644 index 00000000..ce361d84 --- /dev/null +++ b/src/main/java/net/lingala/zip4j/io/inputstream/SplitFileInputStream.java @@ -0,0 +1,13 @@ +package net.lingala.zip4j.io.inputstream; + +import net.lingala.zip4j.model.FileHeader; + +import java.io.IOException; +import java.io.InputStream; + +// Even though this abstract class has only abstract method definitions, it is not implemented as an interface because +// implementations of this class has to be used as an inputstream to ZipInputStream +public abstract class SplitFileInputStream extends InputStream { + + public abstract void prepareExtractionForFileHeader(FileHeader fileHeader) throws IOException; +} diff --git a/src/main/java/net/lingala/zip4j/io/inputstream/SplitInputStream.java b/src/main/java/net/lingala/zip4j/io/inputstream/ZipStandardSplitFileInputStream.java similarity index 72% rename from src/main/java/net/lingala/zip4j/io/inputstream/SplitInputStream.java rename to src/main/java/net/lingala/zip4j/io/inputstream/ZipStandardSplitFileInputStream.java index e0de8bce..cf877132 100644 --- a/src/main/java/net/lingala/zip4j/io/inputstream/SplitInputStream.java +++ b/src/main/java/net/lingala/zip4j/io/inputstream/ZipStandardSplitFileInputStream.java @@ -6,27 +6,25 @@ import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; -import java.io.InputStream; import java.io.RandomAccessFile; -public abstract class SplitInputStream extends InputStream { +/** + * A split input stream for zip file split as per zip specification. They end with .z01, .z02... .zip + */ +public class ZipStandardSplitFileInputStream extends SplitFileInputStream { protected RandomAccessFile randomAccessFile; protected File zipFile; - + private int lastSplitZipFileNumber; private boolean isSplitZipArchive; private int currentSplitFileCounter = 0; private byte[] singleByteArray = new byte[1]; - public SplitInputStream(File zipFile, boolean isSplitZipArchive, int lastSplitZipFileNumber) throws FileNotFoundException { + public ZipStandardSplitFileInputStream(File zipFile, boolean isSplitZipArchive, int lastSplitZipFileNumber) throws FileNotFoundException { this.randomAccessFile = new RandomAccessFile(zipFile, RandomAccessFileMode.READ.getValue()); this.zipFile = zipFile; this.isSplitZipArchive = isSplitZipArchive; - - - if (isSplitZipArchive) { - currentSplitFileCounter = lastSplitZipFileNumber; - } + this.lastSplitZipFileNumber = lastSplitZipFileNumber; } @Override @@ -60,6 +58,7 @@ public int read(byte[] b, int off, int len) throws IOException { return readLen; } + @Override public void prepareExtractionForFileHeader(FileHeader fileHeader) throws IOException { if (isSplitZipArchive && (currentSplitFileCounter != fileHeader.getDiskNumberStart())) { @@ -70,6 +69,13 @@ public void prepareExtractionForFileHeader(FileHeader fileHeader) throws IOExcep randomAccessFile.seek(fileHeader.getOffsetLocalHeader()); } + @Override + public void close() throws IOException { + if (randomAccessFile != null) { + randomAccessFile.close(); + } + } + protected void openRandomAccessFileForIndex(int zipFileIndex) throws IOException { File nextSplitFile = getNextSplitFile(zipFileIndex); if (!nextSplitFile.exists()) { @@ -79,12 +85,18 @@ protected void openRandomAccessFileForIndex(int zipFileIndex) throws IOException randomAccessFile = new RandomAccessFile(nextSplitFile, RandomAccessFileMode.READ.getValue()); } - protected abstract File getNextSplitFile(int zipFileIndex) throws IOException; + protected File getNextSplitFile(int zipFileIndex) throws IOException { + if (zipFileIndex == lastSplitZipFileNumber) { + return zipFile; + } - @Override - public void close() throws IOException { - if (randomAccessFile != null) { - randomAccessFile.close(); + String currZipFileNameWithPath = zipFile.getCanonicalPath(); + String extensionSubString = ".z0"; + if (zipFileIndex >= 9) { + extensionSubString = ".z"; } + + return new File(currZipFileNameWithPath.substring(0, + currZipFileNameWithPath.lastIndexOf(".")) + extensionSubString + (zipFileIndex + 1)); } } diff --git a/src/main/java/net/lingala/zip4j/io/inputstream/ZipStandardSplitInputStream.java b/src/main/java/net/lingala/zip4j/io/inputstream/ZipStandardSplitInputStream.java deleted file mode 100644 index 77c1f4c7..00000000 --- a/src/main/java/net/lingala/zip4j/io/inputstream/ZipStandardSplitInputStream.java +++ /dev/null @@ -1,34 +0,0 @@ -package net.lingala.zip4j.io.inputstream; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; - -/** - * A split input stream for zip file split as per zip specification. They end with .z01, .z02... .zip - */ -public class ZipStandardSplitInputStream extends SplitInputStream { - - private int lastSplitZipFileNumber; - - public ZipStandardSplitInputStream(File zipFile, boolean isSplitZipArchive, int lastSplitZipFileNumber) throws FileNotFoundException { - super(zipFile, isSplitZipArchive, lastSplitZipFileNumber); - this.lastSplitZipFileNumber = lastSplitZipFileNumber; - } - - @Override - protected File getNextSplitFile(int zipFileIndex) throws IOException { - if (zipFileIndex == lastSplitZipFileNumber) { - return zipFile; - } - - String currZipFileNameWithPath = zipFile.getCanonicalPath(); - String extensionSubString = ".z0"; - if (zipFileIndex >= 9) { - extensionSubString = ".z"; - } - - return new File(currZipFileNameWithPath.substring(0, - currZipFileNameWithPath.lastIndexOf(".")) + extensionSubString + (zipFileIndex + 1)); - } -} diff --git a/src/main/java/net/lingala/zip4j/tasks/ExtractAllFilesTask.java b/src/main/java/net/lingala/zip4j/tasks/ExtractAllFilesTask.java index 5766c89f..f57d5188 100644 --- a/src/main/java/net/lingala/zip4j/tasks/ExtractAllFilesTask.java +++ b/src/main/java/net/lingala/zip4j/tasks/ExtractAllFilesTask.java @@ -1,6 +1,6 @@ package net.lingala.zip4j.tasks; -import net.lingala.zip4j.io.inputstream.SplitInputStream; +import net.lingala.zip4j.io.inputstream.SplitFileInputStream; import net.lingala.zip4j.io.inputstream.ZipInputStream; import net.lingala.zip4j.model.FileHeader; import net.lingala.zip4j.model.UnzipParameters; @@ -17,7 +17,7 @@ public class ExtractAllFilesTask extends AbstractExtractFileTask { private final char[] password; - private SplitInputStream splitInputStream; + private SplitFileInputStream splitInputStream; public ExtractAllFilesTask(ZipModel zipModel, char[] password, UnzipParameters unzipParameters, AsyncTaskParameters asyncTaskParameters) { diff --git a/src/main/java/net/lingala/zip4j/tasks/ExtractFileTask.java b/src/main/java/net/lingala/zip4j/tasks/ExtractFileTask.java index 1c1dbbaf..700d7adb 100644 --- a/src/main/java/net/lingala/zip4j/tasks/ExtractFileTask.java +++ b/src/main/java/net/lingala/zip4j/tasks/ExtractFileTask.java @@ -2,7 +2,7 @@ import net.lingala.zip4j.exception.ZipException; import net.lingala.zip4j.headers.HeaderUtil; -import net.lingala.zip4j.io.inputstream.SplitInputStream; +import net.lingala.zip4j.io.inputstream.SplitFileInputStream; import net.lingala.zip4j.io.inputstream.ZipInputStream; import net.lingala.zip4j.model.FileHeader; import net.lingala.zip4j.model.UnzipParameters; @@ -26,7 +26,7 @@ public class ExtractFileTask extends AbstractExtractFileTask { private char[] password; - private SplitInputStream splitInputStream; + private SplitFileInputStream splitInputStream; public ExtractFileTask(ZipModel zipModel, char[] password, UnzipParameters unzipParameters, AsyncTaskParameters asyncTaskParameters) { diff --git a/src/main/java/net/lingala/zip4j/util/UnzipUtil.java b/src/main/java/net/lingala/zip4j/util/UnzipUtil.java index 0238252a..343ab3fc 100755 --- a/src/main/java/net/lingala/zip4j/util/UnzipUtil.java +++ b/src/main/java/net/lingala/zip4j/util/UnzipUtil.java @@ -1,10 +1,10 @@ package net.lingala.zip4j.util; import net.lingala.zip4j.exception.ZipException; -import net.lingala.zip4j.io.inputstream.NumberedSplitInputStream; -import net.lingala.zip4j.io.inputstream.SplitInputStream; +import net.lingala.zip4j.io.inputstream.NumberedSplitFileInputStream; +import net.lingala.zip4j.io.inputstream.SplitFileInputStream; import net.lingala.zip4j.io.inputstream.ZipInputStream; -import net.lingala.zip4j.io.inputstream.ZipStandardSplitInputStream; +import net.lingala.zip4j.io.inputstream.ZipStandardSplitFileInputStream; import net.lingala.zip4j.model.FileHeader; import net.lingala.zip4j.model.ZipModel; @@ -21,7 +21,7 @@ public class UnzipUtil { public static ZipInputStream createZipInputStream(ZipModel zipModel, FileHeader fileHeader, char[] password) throws IOException { - SplitInputStream splitInputStream = null; + SplitFileInputStream splitInputStream = null; try { splitInputStream = createSplitInputStream(zipModel); splitInputStream.prepareExtractionForFileHeader(fileHeader); @@ -51,15 +51,14 @@ public static void applyFileAttributes(FileHeader fileHeader, File file) { } } - public static SplitInputStream createSplitInputStream(ZipModel zipModel) throws IOException { + public static SplitFileInputStream createSplitInputStream(ZipModel zipModel) throws IOException { File zipFile = zipModel.getZipFile(); if (zipFile.getName().endsWith(InternalZipConstants.SEVEN_ZIP_SPLIT_FILE_EXTENSION_PATTERN)) { - return new NumberedSplitInputStream(zipModel.getZipFile(), true, - zipModel.getEndOfCentralDirectoryRecord().getNumberOfThisDisk()); + return new NumberedSplitFileInputStream(zipModel.getZipFile()); } - return new ZipStandardSplitInputStream(zipModel.getZipFile(), zipModel.isSplitArchive(), + return new ZipStandardSplitFileInputStream(zipModel.getZipFile(), zipModel.isSplitArchive(), zipModel.getEndOfCentralDirectoryRecord().getNumberOfThisDisk()); } diff --git a/src/test/java/net/lingala/zip4j/ExtractZipFileIT.java b/src/test/java/net/lingala/zip4j/ExtractZipFileIT.java index 78c51994..bb97031e 100644 --- a/src/test/java/net/lingala/zip4j/ExtractZipFileIT.java +++ b/src/test/java/net/lingala/zip4j/ExtractZipFileIT.java @@ -516,7 +516,7 @@ public void testExtractZipFileCRCError() throws IOException { @Test public void testExtractZipFileOf7ZipFormatSplitWithoutEncryption() throws IOException { List filesToAddToZip = new ArrayList<>(FILES_TO_ADD); - filesToAddToZip.add(getTestFileFromResources("file_PDF_1MB.pdf")); + filesToAddToZip.add(0, getTestFileFromResources("file_PDF_1MB.pdf")); File firstSplitFile = createZipFileAndSplit(filesToAddToZip, 102400, false, null); verifyZipFileByExtractingAllFiles(firstSplitFile, outputFolder, 4); } @@ -524,7 +524,7 @@ public void testExtractZipFileOf7ZipFormatSplitWithoutEncryption() throws IOExce @Test public void testExtractZipFileOf7ZipFormatSplitWithAESEncryption() throws IOException { List filesToAddToZip = new ArrayList<>(FILES_TO_ADD); - filesToAddToZip.add(getTestFileFromResources("file_PDF_1MB.pdf")); + filesToAddToZip.add(0, getTestFileFromResources("file_PDF_1MB.pdf")); File firstSplitFile = createZipFileAndSplit(filesToAddToZip, 102000, true, EncryptionMethod.AES); verifyZipFileByExtractingAllFiles(firstSplitFile, PASSWORD, outputFolder, 4); } diff --git a/src/test/java/net/lingala/zip4j/util/UnzipUtilIT.java b/src/test/java/net/lingala/zip4j/util/UnzipUtilIT.java index 7faadc1b..a00c283f 100644 --- a/src/test/java/net/lingala/zip4j/util/UnzipUtilIT.java +++ b/src/test/java/net/lingala/zip4j/util/UnzipUtilIT.java @@ -3,9 +3,9 @@ import net.lingala.zip4j.AbstractIT; import net.lingala.zip4j.ZipFile; import net.lingala.zip4j.exception.ZipException; -import net.lingala.zip4j.io.inputstream.NumberedSplitInputStream; -import net.lingala.zip4j.io.inputstream.SplitInputStream; -import net.lingala.zip4j.io.inputstream.ZipStandardSplitInputStream; +import net.lingala.zip4j.io.inputstream.NumberedSplitFileInputStream; +import net.lingala.zip4j.io.inputstream.SplitFileInputStream; +import net.lingala.zip4j.io.inputstream.ZipStandardSplitFileInputStream; import net.lingala.zip4j.model.FileHeader; import net.lingala.zip4j.model.ZipModel; import net.lingala.zip4j.testutils.TestUtils; @@ -109,9 +109,9 @@ public void testCreateSplitInputStreamForNumberedSplitZipReturnsInstance() throw ZipModel zipModel = createZipModel(); zipModel.setZipFile(zipFile); - SplitInputStream splitInputStream = UnzipUtil.createSplitInputStream(zipModel); + SplitFileInputStream splitInputStream = UnzipUtil.createSplitInputStream(zipModel); - assertThat(splitInputStream).isInstanceOf(NumberedSplitInputStream.class); + assertThat(splitInputStream).isInstanceOf(NumberedSplitFileInputStream.class); } @Test @@ -119,9 +119,9 @@ public void testCreateSplitInputStreamForNonNumberedSplitZipReturnsInstance() th temporaryFolder.newFile(generatedZipFile.getName()); ZipModel zipModel = createZipModel(); - SplitInputStream splitInputStream = UnzipUtil.createSplitInputStream(zipModel); + SplitFileInputStream splitInputStream = UnzipUtil.createSplitInputStream(zipModel); - assertThat(splitInputStream).isInstanceOf(ZipStandardSplitInputStream.class); + assertThat(splitInputStream).isInstanceOf(ZipStandardSplitFileInputStream.class); } private ZipFile createZipFile() throws ZipException {