You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by bo...@apache.org on 2019/12/08 13:31:23 UTC
[commons-compress] 01/04: COMPRESS-477:add support for splitted zip
file
This is an automated email from the ASF dual-hosted git repository.
bodewig pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-compress.git
commit 0df4d084182c2c2662b777ee2c3b04a1c42bbc66
Author: Lee <pe...@gmail.com>
AuthorDate: Mon Oct 28 16:04:35 2019 +0800
COMPRESS-477:add support for splitted zip file
add support for splitted zip file for ZipArchiveInputStream
---
.../archivers/zip/ZipArchiveInputStream.java | 34 ++++--
.../commons/compress/archivers/zip/ZipFile.java | 5 +-
.../zip}/ZipSplitReadOnlySeekableByteChannel.java | 114 ++++++++++++---------
.../commons/compress/compressors/FileNameUtil.java | 4 +-
.../utils/MultiReadOnlySeekableByteChannel.java | 23 ++++-
.../compress/utils/ZipSplitSegmentComparator.java | 45 --------
.../archivers/zip/ZipArchiveInputStreamTest.java | 72 +++++++++++++
.../compress/archivers/zip/ZipFileTest.java | 17 ++-
.../ZipSplitReadOnlySeekableByteChannelTest.java | 13 +--
.../split_zip_created_by_winrar.z01 | Bin 262144 -> 262144 bytes
.../split_zip_created_by_winrar.z02 | Bin 262044 -> 262144 bytes
.../split_zip_created_by_winrar.zip | Bin 41809 -> 50536 bytes
.../zip_to_compare_created_by_winrar.zip | Bin 0 -> 574820 bytes
.../zip_to_compare_created_by_zip.zip | Bin 0 -> 582047 bytes
.../zip_to_compare_created_by_zip_zip64.zip | Bin 0 -> 584681 bytes
15 files changed, 202 insertions(+), 125 deletions(-)
diff --git a/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveInputStream.java b/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveInputStream.java
index 48ad5d5..be5a0fd 100644
--- a/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveInputStream.java
+++ b/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveInputStream.java
@@ -120,6 +120,9 @@ public class ZipArchiveInputStream extends ArchiveInputStream implements InputSt
/** Count decompressed bytes for current entry */
private long uncompressedCount = 0;
+ /** Whether the stream will try to skip the zip split signature(08074B50) at the beginning **/
+ private final boolean skipSplitSig;
+
private static final int LFH_LEN = 30;
/*
local file header signature WORD
@@ -213,12 +216,34 @@ public class ZipArchiveInputStream extends ArchiveInputStream implements InputSt
final String encoding,
final boolean useUnicodeExtraFields,
final boolean allowStoredEntriesWithDataDescriptor) {
+ this(inputStream, encoding, useUnicodeExtraFields, allowStoredEntriesWithDataDescriptor, false);
+ }
+
+ /**
+ * Create an instance using the specified encoding
+ * @param inputStream the stream to wrap
+ * @param encoding the encoding to use for file names, use null
+ * for the platform's default encoding
+ * @param useUnicodeExtraFields whether to use InfoZIP Unicode
+ * Extra Fields (if present) to set the file names.
+ * @param allowStoredEntriesWithDataDescriptor whether the stream
+ * will try to read STORED entries that use a data descriptor
+ * @param skipSplitSig Whether the stream will try to skip the
+ * zip split signature(08074B50) at the beginning
+ * @since 1.20
+ */
+ public ZipArchiveInputStream(final InputStream inputStream,
+ final String encoding,
+ final boolean useUnicodeExtraFields,
+ final boolean allowStoredEntriesWithDataDescriptor,
+ final boolean skipSplitSig) {
this.encoding = encoding;
zipEncoding = ZipEncodingHelper.getZipEncoding(encoding);
this.useUnicodeExtraFields = useUnicodeExtraFields;
in = new PushbackInputStream(inputStream, buf.capacity());
this.allowStoredEntriesWithDataDescriptor =
allowStoredEntriesWithDataDescriptor;
+ this.skipSplitSig = skipSplitSig;
// haven't read anything so far
buf.limit(0);
}
@@ -367,13 +392,10 @@ public class ZipArchiveInputStream extends ArchiveInputStream implements InputSt
private void readFirstLocalFileHeader(final byte[] lfh) throws IOException {
readFully(lfh);
final ZipLong sig = new ZipLong(lfh);
- if (sig.equals(ZipLong.DD_SIG)) {
- throw new UnsupportedZipFeatureException(UnsupportedZipFeatureException.Feature.SPLITTING);
- }
- if (sig.equals(ZipLong.SINGLE_SEGMENT_SPLIT_MARKER)) {
- // The archive is not really split as only one segment was
- // needed in the end. Just skip over the marker.
+ // the split zip signature(08074B50) should only be skipped when the skipSplitSig is set
+ if (sig.equals(ZipLong.SINGLE_SEGMENT_SPLIT_MARKER) || (skipSplitSig && sig.equals(ZipLong.DD_SIG))) {
+ // Just skip over the marker.
final byte[] missedLfhBytes = new byte[4];
readFully(missedLfhBytes);
System.arraycopy(lfh, 4, lfh, 0, LFH_LEN - 4);
diff --git a/src/main/java/org/apache/commons/compress/archivers/zip/ZipFile.java b/src/main/java/org/apache/commons/compress/archivers/zip/ZipFile.java
index e89fe96..ec3a6de 100644
--- a/src/main/java/org/apache/commons/compress/archivers/zip/ZipFile.java
+++ b/src/main/java/org/apache/commons/compress/archivers/zip/ZipFile.java
@@ -48,7 +48,6 @@ import org.apache.commons.compress.compressors.deflate64.Deflate64CompressorInpu
import org.apache.commons.compress.utils.CountingInputStream;
import org.apache.commons.compress.utils.IOUtils;
import org.apache.commons.compress.utils.InputStreamStatistics;
-import org.apache.commons.compress.utils.ZipSplitReadOnlySeekableByteChannel;
import static org.apache.commons.compress.archivers.zip.ZipConstants.DWORD;
import static org.apache.commons.compress.archivers.zip.ZipConstants.SHORT;
@@ -147,7 +146,7 @@ public class ZipFile implements Closeable {
/**
* Whether the zip archive is a splite zip archive
*/
- private boolean isSplitZipArchive = false;
+ private final boolean isSplitZipArchive;
// cached buffers - must only be used locally in the class (COMPRESS-172 - reduce garbage collection)
private final byte[] dwordBuf = new byte[DWORD];
@@ -361,6 +360,8 @@ public class ZipFile implements Closeable {
throws IOException {
if(channel instanceof ZipSplitReadOnlySeekableByteChannel) {
isSplitZipArchive = true;
+ } else {
+ isSplitZipArchive = false;
}
this.archiveName = archiveName;
diff --git a/src/main/java/org/apache/commons/compress/utils/ZipSplitReadOnlySeekableByteChannel.java b/src/main/java/org/apache/commons/compress/archivers/zip/ZipSplitReadOnlySeekableByteChannel.java
similarity index 68%
rename from src/main/java/org/apache/commons/compress/utils/ZipSplitReadOnlySeekableByteChannel.java
rename to src/main/java/org/apache/commons/compress/archivers/zip/ZipSplitReadOnlySeekableByteChannel.java
index f483eda..eae00ba 100644
--- a/src/main/java/org/apache/commons/compress/utils/ZipSplitReadOnlySeekableByteChannel.java
+++ b/src/main/java/org/apache/commons/compress/archivers/zip/ZipSplitReadOnlySeekableByteChannel.java
@@ -16,11 +16,11 @@
*
*/
-package org.apache.commons.compress.utils;
+package org.apache.commons.compress.archivers.zip;
import org.apache.commons.compress.archivers.ArchiveStreamFactory;
-import org.apache.commons.compress.archivers.zip.ZipLong;
import org.apache.commons.compress.compressors.FileNameUtil;
+import org.apache.commons.compress.utils.MultiReadOnlySeekableByteChannel;
import java.io.File;
import java.io.IOException;
@@ -31,21 +31,20 @@ import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
+import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.regex.Pattern;
public class ZipSplitReadOnlySeekableByteChannel extends MultiReadOnlySeekableByteChannel {
- protected final int ZIP_SPLIT_SIGNATURE_LENGTH = 4;
- protected ByteBuffer zipSplitSignatureByteBuffer = ByteBuffer.allocate(ZIP_SPLIT_SIGNATURE_LENGTH);
+ private final int ZIP_SPLIT_SIGNATURE_LENGTH = 4;
+ private ByteBuffer zipSplitSignatureByteBuffer = ByteBuffer.allocate(ZIP_SPLIT_SIGNATURE_LENGTH);
/**
* Concatenates the given channels.
* the channels should be add in ascending order, e.g. z01, z02, ... z99, zip
* please note that the .zip file is the last segment and should be added as the last one in the channels
- *
- * The first 4 bytes of split zip signature will be taken into consideration by Inflator,
- * so we don't need to skip them
+ * <p>
*
* @param channels the channels to concatenate
* @throws NullPointerException if channels is null
@@ -53,48 +52,40 @@ public class ZipSplitReadOnlySeekableByteChannel extends MultiReadOnlySeekableBy
public ZipSplitReadOnlySeekableByteChannel(List<SeekableByteChannel> channels) throws IOException {
super(channels);
- // each split zip segment should begin with zip split signature
+ // the first split zip segment should begin with zip split signature
validSplitSignature(channels);
}
/**
- * the first 4 bytes of zip split segments should be the zip split signature(0x08074B50)
+ * Based on the zip specification:
+ * <p>
+ * 8.5.3 Spanned/Split archives created using PKZIP for Windows
+ * (V2.50 or greater), PKZIP Command Line (V2.50 or greater),
+ * or PKZIP Explorer will include a special spanning
+ * signature as the first 4 bytes of the first segment of
+ * the archive. This signature (0x08074b50) will be
+ * followed immediately by the local header signature for
+ * the first file in the archive.
+ * <p>
+ * the first 4 bytes of the first zip split segment should be the zip split signature(0x08074B50)
*
* @param channels channels to be valided
* @throws IOException
*/
private void validSplitSignature(final List<SeekableByteChannel> channels) throws IOException {
- for(int i = 0;i < channels.size();i++) {
- SeekableByteChannel channel = channels.get(i);
- // the zip split file signature is always at the beginning of the segment
- channel.position(0L);
-
- channel.read(zipSplitSignatureByteBuffer);
- final ZipLong signature = new ZipLong(zipSplitSignatureByteBuffer.array());
- if(!signature.equals(ZipLong.DD_SIG)) {
- channel.position(0L);
- throw new IOException("No." + (i + 1) + " split zip file is not begin with split zip file signature");
- }
-
+ SeekableByteChannel channel = channels.get(0);
+ // the zip split file signature is at the beginning of the first split segment
+ channel.position(0L);
+
+ zipSplitSignatureByteBuffer.rewind();
+ channel.read(zipSplitSignatureByteBuffer);
+ final ZipLong signature = new ZipLong(zipSplitSignatureByteBuffer.array());
+ if (!signature.equals(ZipLong.DD_SIG)) {
channel.position(0L);
+ throw new IOException("The first zip split segment is not begin with split zip file signature");
}
- }
- /**
- * set the position based on the given disk number and relative offset
- *
- * @param diskNumber the disk number of split zip files
- * @param relativeOffset the offset in the split zip segment with given disk number
- * @return global position of all split zip files as if they are a single channel
- * @throws IOException
- */
- public synchronized SeekableByteChannel position(long diskNumber, long relativeOffset) throws IOException {
- long globalPosition = relativeOffset;
- for(int i = 0; i < diskNumber;i++) {
- globalPosition += channels.get(i).size();
- }
-
- return position(globalPosition);
+ channel.position(0L);
}
/**
@@ -102,8 +93,8 @@ public class ZipSplitReadOnlySeekableByteChannel extends MultiReadOnlySeekableBy
*
* @param channels the channels to concatenate, note that the LAST CHANNEL of channels should be the LAST SEGMENT(.zip)
* and theses channels should be added in correct order (e.g. .z01, .z02... .z99, .zip)
- * @throws NullPointerException if channels is null
* @return SeekableByteChannel that concatenates all provided channels
+ * @throws NullPointerException if channels is null
*/
public static SeekableByteChannel forSeekableByteChannels(SeekableByteChannel... channels) throws IOException {
if (Objects.requireNonNull(channels, "channels must not be null").length == 1) {
@@ -116,18 +107,18 @@ public class ZipSplitReadOnlySeekableByteChannel extends MultiReadOnlySeekableBy
* Concatenates the given channels.
*
* @param lastSegmentChannel channel of the last segment of split zip segments, its extension should be .zip
- * @param channels the channels to concatenate except for the last segment,
- * note theses channels should be added in correct order (e.g. .z01, .z02... .z99)
+ * @param channels the channels to concatenate except for the last segment,
+ * note theses channels should be added in correct order (e.g. .z01, .z02... .z99)
* @return SeekableByteChannel that concatenates all provided channels
* @throws NullPointerException if lastSegmentChannel or channels is null
*/
public static SeekableByteChannel forSeekableByteChannels(SeekableByteChannel lastSegmentChannel, Iterable<SeekableByteChannel> channels) throws IOException {
- if(channels == null || lastSegmentChannel == null) {
+ if (channels == null || lastSegmentChannel == null) {
throw new NullPointerException("channels must not be null");
}
List<SeekableByteChannel> channelsList = new ArrayList<>();
- for(SeekableByteChannel channel : channels) {
+ for (SeekableByteChannel channel : channels) {
channelsList.add(channel);
}
channelsList.add(lastSegmentChannel);
@@ -145,7 +136,7 @@ public class ZipSplitReadOnlySeekableByteChannel extends MultiReadOnlySeekableBy
*/
public static SeekableByteChannel buildFromLastSplitSegment(File lastSegmentFile) throws IOException {
String extension = FileNameUtil.getExtension(lastSegmentFile.getCanonicalPath());
- if(!extension.equals(ArchiveStreamFactory.ZIP)) {
+ if (!extension.equalsIgnoreCase(ArchiveStreamFactory.ZIP)) {
throw new IllegalArgumentException("The extension of last zip splite segment should be .zip");
}
@@ -154,9 +145,9 @@ public class ZipSplitReadOnlySeekableByteChannel extends MultiReadOnlySeekableBy
ArrayList<File> splitZipSegments = new ArrayList<>();
// zip split segments should be like z01,z02....z(n-1) based on the zip specification
- String pattern = fileBaseName + ".z[0-9]+";
- for(File file : parent.listFiles()) {
- if(!Pattern.matches(pattern, file.getName())) {
+ Pattern pattern = Pattern.compile(Pattern.quote(fileBaseName) + ".[zZ][0-9]+");
+ for (File file : parent.listFiles()) {
+ if (!pattern.matcher(file.getName()).matches()) {
continue;
}
@@ -172,9 +163,9 @@ public class ZipSplitReadOnlySeekableByteChannel extends MultiReadOnlySeekableBy
*
* @param files the files to concatenate, note that the LAST FILE of files should be the LAST SEGMENT(.zip)
* and theses files should be added in correct order (e.g. .z01, .z02... .z99, .zip)
- * @throws NullPointerException if files is null
- * @throws IOException if opening a channel for one of the files fails
* @return SeekableByteChannel that concatenates all provided files
+ * @throws NullPointerException if files is null
+ * @throws IOException if opening a channel for one of the files fails
*/
public static SeekableByteChannel forFiles(File... files) throws IOException {
List<SeekableByteChannel> channels = new ArrayList<>();
@@ -191,14 +182,14 @@ public class ZipSplitReadOnlySeekableByteChannel extends MultiReadOnlySeekableBy
* Concatenates the given files.
*
* @param lastSegmentFile the last segment of split zip segments, its extension should be .zip
- * @param files the files to concatenate except for the last segment,
- * note theses files should be added in correct order (e.g. .z01, .z02... .z99)
+ * @param files the files to concatenate except for the last segment,
+ * note theses files should be added in correct order (e.g. .z01, .z02... .z99)
* @return SeekableByteChannel that concatenates all provided files
* @throws IOException
* @throws NullPointerException if files or lastSegmentFile is null
*/
public static SeekableByteChannel forFiles(File lastSegmentFile, Iterable<File> files) throws IOException {
- if(files == null || lastSegmentFile == null) {
+ if (files == null || lastSegmentFile == null) {
throw new NullPointerException("files must not be null");
}
@@ -211,4 +202,25 @@ public class ZipSplitReadOnlySeekableByteChannel extends MultiReadOnlySeekableBy
File[] filesArray = new File[filesList.size()];
return forFiles(filesList.toArray(filesArray));
}
+
+ public static class ZipSplitSegmentComparator implements Comparator<File> {
+ @Override
+ public int compare(File file1, File file2) {
+ String extension1 = FileNameUtil.getExtension(file1.getPath());
+ String extension2 = FileNameUtil.getExtension(file2.getPath());
+
+ if (!extension1.startsWith("z")) {
+ return -1;
+ }
+
+ if (!extension2.startsWith("z")) {
+ return 1;
+ }
+
+ Integer splitSegmentNumber1 = Integer.parseInt(extension1.substring(1));
+ Integer splitSegmentNumber2 = Integer.parseInt(extension2.substring(1));
+
+ return splitSegmentNumber1.compareTo(splitSegmentNumber2);
+ }
+ }
}
diff --git a/src/main/java/org/apache/commons/compress/compressors/FileNameUtil.java b/src/main/java/org/apache/commons/compress/compressors/FileNameUtil.java
index 3b9d76c..ec3f0e9 100644
--- a/src/main/java/org/apache/commons/compress/compressors/FileNameUtil.java
+++ b/src/main/java/org/apache/commons/compress/compressors/FileNameUtil.java
@@ -18,6 +18,7 @@
*/
package org.apache.commons.compress.compressors;
+import java.io.File;
import java.util.Collections;
import java.util.HashMap;
import java.util.Locale;
@@ -212,8 +213,7 @@ public class FileNameUtil {
return null;
}
- int lastSeparatorPosition = Math.max(filename.lastIndexOf('/'), filename.lastIndexOf('\\'));
- String name = filename.substring(lastSeparatorPosition + 1);
+ String name = new File(filename).getName();
int extensionPosition = name.lastIndexOf('.');
if(extensionPosition < 0) {
diff --git a/src/main/java/org/apache/commons/compress/utils/MultiReadOnlySeekableByteChannel.java b/src/main/java/org/apache/commons/compress/utils/MultiReadOnlySeekableByteChannel.java
index b9eee89..5129dbd 100644
--- a/src/main/java/org/apache/commons/compress/utils/MultiReadOnlySeekableByteChannel.java
+++ b/src/main/java/org/apache/commons/compress/utils/MultiReadOnlySeekableByteChannel.java
@@ -44,9 +44,9 @@ import java.util.Objects;
*/
public class MultiReadOnlySeekableByteChannel implements SeekableByteChannel {
- protected final List<SeekableByteChannel> channels;
- protected long globalPosition;
- protected int currentChannelIdx;
+ private final List<SeekableByteChannel> channels;
+ private long globalPosition;
+ private int currentChannelIdx;
/**
* Concatenates the given channels.
@@ -122,6 +122,23 @@ public class MultiReadOnlySeekableByteChannel implements SeekableByteChannel {
return globalPosition;
}
+ /**
+ * set the position based on the given channel number and relative offset
+ *
+ * @param channelNumber the channel number
+ * @param relativeOffset the relative offset in the corresponding channel
+ * @return global position of all channels as if they are a single channel
+ * @throws IOException
+ */
+ public synchronized SeekableByteChannel position(long channelNumber, long relativeOffset) throws IOException {
+ long globalPosition = relativeOffset;
+ for (int i = 0; i < channelNumber; i++) {
+ globalPosition += channels.get(i).size();
+ }
+
+ return position(globalPosition);
+ }
+
@Override
public long size() throws IOException {
long acc = 0;
diff --git a/src/main/java/org/apache/commons/compress/utils/ZipSplitSegmentComparator.java b/src/main/java/org/apache/commons/compress/utils/ZipSplitSegmentComparator.java
deleted file mode 100644
index 3b0a9e8..0000000
--- a/src/main/java/org/apache/commons/compress/utils/ZipSplitSegmentComparator.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package org.apache.commons.compress.utils;
-
-import org.apache.commons.compress.compressors.FileNameUtil;
-
-import java.io.File;
-import java.util.Comparator;
-
-public class ZipSplitSegmentComparator implements Comparator<File> {
- @Override
- public int compare(File file1, File file2) {
- String extension1 = FileNameUtil.getExtension(file1.getPath());
- String extension2 = FileNameUtil.getExtension(file2.getPath());
-
- if(!extension1.startsWith("z")) {
- return -1;
- }
-
- if(!extension2.startsWith("z")) {
- return 1;
- }
-
- Integer splitSegmentNumber1 = Integer.parseInt(extension1.substring(1));
- Integer splitSegmentNumber2 = Integer.parseInt(extension2.substring(1));
-
- return splitSegmentNumber1.compareTo(splitSegmentNumber2);
- }
-}
diff --git a/src/test/java/org/apache/commons/compress/archivers/zip/ZipArchiveInputStreamTest.java b/src/test/java/org/apache/commons/compress/archivers/zip/ZipArchiveInputStreamTest.java
index 43a509e..f108878 100644
--- a/src/test/java/org/apache/commons/compress/archivers/zip/ZipArchiveInputStreamTest.java
+++ b/src/test/java/org/apache/commons/compress/archivers/zip/ZipArchiveInputStreamTest.java
@@ -34,6 +34,8 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.nio.channels.Channels;
+import java.nio.channels.SeekableByteChannel;
import java.util.Arrays;
import java.util.zip.ZipException;
@@ -596,6 +598,76 @@ public class ZipArchiveInputStreamTest {
}
}
+ @Test
+ public void testSplitZipCreatedByZip() throws IOException {
+ File lastFile = getFile("COMPRESS-477/split_zip_created_by_zip/split_zip_created_by_zip.zip");
+ SeekableByteChannel channel = ZipSplitReadOnlySeekableByteChannel.buildFromLastSplitSegment(lastFile);
+ InputStream inputStream = Channels.newInputStream(channel);
+ ZipArchiveInputStream splitInputStream = new ZipArchiveInputStream(inputStream, ZipEncodingHelper.UTF8, true, false, true);
+
+ File fileToCompare = getFile("COMPRESS-477/split_zip_created_by_zip/zip_to_compare_created_by_zip.zip");
+ ZipArchiveInputStream inputStreamToCompare = new ZipArchiveInputStream(new FileInputStream(fileToCompare), ZipEncodingHelper.UTF8, true, false, true);
+
+ ArchiveEntry entry;
+ while((entry = splitInputStream.getNextEntry()) != null && inputStreamToCompare.getNextEntry() != null) {
+ if(entry.isDirectory()) {
+ continue;
+ }
+ Assert.assertTrue(shaded.org.apache.commons.io.IOUtils.contentEquals(splitInputStream, inputStreamToCompare));
+ }
+ }
+
+ @Test
+ public void testSplitZipCreatedByZipOfZip64() throws IOException {
+ File lastFile = getFile("COMPRESS-477/split_zip_created_by_zip/split_zip_created_by_zip_zip64.zip");
+ SeekableByteChannel channel = ZipSplitReadOnlySeekableByteChannel.buildFromLastSplitSegment(lastFile);
+ InputStream inputStream = Channels.newInputStream(channel);
+ ZipArchiveInputStream splitInputStream = new ZipArchiveInputStream(inputStream, ZipEncodingHelper.UTF8, true, false, true);
+
+ File fileToCompare = getFile("COMPRESS-477/split_zip_created_by_zip/zip_to_compare_created_by_zip_zip64.zip");
+ ZipArchiveInputStream inputStreamToCompare = new ZipArchiveInputStream(new FileInputStream(fileToCompare), ZipEncodingHelper.UTF8, true, false, true);
+
+ ArchiveEntry entry;
+ while((entry = splitInputStream.getNextEntry()) != null && inputStreamToCompare.getNextEntry() != null) {
+ if(entry.isDirectory()) {
+ continue;
+ }
+ Assert.assertTrue(shaded.org.apache.commons.io.IOUtils.contentEquals(splitInputStream, inputStreamToCompare));
+ }
+ }
+
+ @Test
+ public void testSplitZipCreatedByWinrar() throws IOException {
+ File lastFile = getFile("COMPRESS-477/split_zip_created_by_winrar/split_zip_created_by_winrar.zip");
+ SeekableByteChannel channel = ZipSplitReadOnlySeekableByteChannel.buildFromLastSplitSegment(lastFile);
+ InputStream inputStream = Channels.newInputStream(channel);
+ ZipArchiveInputStream splitInputStream = new ZipArchiveInputStream(inputStream, ZipEncodingHelper.UTF8, true, false, true);
+
+ File fileToCompare = getFile("COMPRESS-477/split_zip_created_by_winrar/zip_to_compare_created_by_winrar.zip");
+ ZipArchiveInputStream inputStreamToCompare = new ZipArchiveInputStream(new FileInputStream(fileToCompare), ZipEncodingHelper.UTF8, true, false, true);
+
+ ArchiveEntry entry;
+ while((entry = splitInputStream.getNextEntry()) != null && inputStreamToCompare.getNextEntry() != null) {
+ if(entry.isDirectory()) {
+ continue;
+ }
+ Assert.assertTrue(shaded.org.apache.commons.io.IOUtils.contentEquals(splitInputStream, inputStreamToCompare));
+ }
+ }
+
+ @Test
+ public void testSplitZipCreatedByZipThrowsException() throws IOException {
+ thrown.expect(EOFException.class);
+ File zipSplitFile = getFile("COMPRESS-477/split_zip_created_by_zip/split_zip_created_by_zip.z01");
+ InputStream fileInputStream = new FileInputStream(zipSplitFile);
+ ZipArchiveInputStream inputStream = new ZipArchiveInputStream(fileInputStream, ZipEncodingHelper.UTF8, true, false, true);
+
+ ArchiveEntry entry = inputStream.getNextEntry();
+ while(entry != null){
+ entry = inputStream.getNextEntry();
+ }
+ }
+
private static byte[] readEntry(ZipArchiveInputStream zip, ZipArchiveEntry zae) throws IOException {
final int len = (int)zae.getSize();
final byte[] buff = new byte[len];
diff --git a/src/test/java/org/apache/commons/compress/archivers/zip/ZipFileTest.java b/src/test/java/org/apache/commons/compress/archivers/zip/ZipFileTest.java
index ba75bbf..bb34632 100644
--- a/src/test/java/org/apache/commons/compress/archivers/zip/ZipFileTest.java
+++ b/src/test/java/org/apache/commons/compress/archivers/zip/ZipFileTest.java
@@ -46,12 +46,9 @@ import java.util.zip.ZipEntry;
import org.apache.commons.compress.utils.IOUtils;
import org.apache.commons.compress.utils.SeekableInMemoryByteChannel;
-import org.apache.commons.compress.utils.ZipSplitReadOnlySeekableByteChannel;
import org.junit.After;
import org.junit.Assert;
import org.junit.Test;
-import shaded.org.apache.commons.io.FileUtils;
-import shaded.org.apache.commons.io.FilenameUtils;
public class ZipFileTest {
private ZipFile zf = null;
@@ -697,8 +694,8 @@ public class ZipFileTest {
@Test
public void extractFileLiesAcrossSplitZipSegmentsCreatedByZip() throws Exception {
File lastFile = getFile("COMPRESS-477/split_zip_created_by_zip/split_zip_created_by_zip.zip");
- SeekableByteChannel splitInputStream = ZipSplitReadOnlySeekableByteChannel.buildFromLastSplitSegment(lastFile);
- zf = new ZipFile(splitInputStream);
+ SeekableByteChannel channel = ZipSplitReadOnlySeekableByteChannel.buildFromLastSplitSegment(lastFile);
+ zf = new ZipFile(channel);
// the compressed content of UnsupportedCompressionAlgorithmException.java lies between .z01 and .z02
ZipArchiveEntry zipEntry = zf.getEntry("commons-compress/src/main/java/org/apache/commons/compress/archivers/dump/UnsupportedCompressionAlgorithmException.java");
@@ -714,8 +711,8 @@ public class ZipFileTest {
@Test
public void extractFileLiesAcrossSplitZipSegmentsCreatedByZipOfZip64() throws Exception {
File lastFile = getFile("COMPRESS-477/split_zip_created_by_zip/split_zip_created_by_zip_zip64.zip");
- SeekableByteChannel splitInputStream = ZipSplitReadOnlySeekableByteChannel.buildFromLastSplitSegment(lastFile);
- zf = new ZipFile(splitInputStream);
+ SeekableByteChannel channel = ZipSplitReadOnlySeekableByteChannel.buildFromLastSplitSegment(lastFile);
+ zf = new ZipFile(channel);
// the compressed content of UnsupportedCompressionAlgorithmException.java lies between .z01 and .z02
ZipArchiveEntry zipEntry = zf.getEntry("commons-compress/src/main/java/org/apache/commons/compress/archivers/dump/UnsupportedCompressionAlgorithmException.java");
@@ -731,11 +728,11 @@ public class ZipFileTest {
@Test
public void extractFileLiesAcrossSplitZipSegmentsCreatedByWinrar() throws Exception {
File lastFile = getFile("COMPRESS-477/split_zip_created_by_winrar/split_zip_created_by_winrar.zip");
- SeekableByteChannel splitInputStream = ZipSplitReadOnlySeekableByteChannel.buildFromLastSplitSegment(lastFile);
- zf = new ZipFile(splitInputStream);
+ SeekableByteChannel channel = ZipSplitReadOnlySeekableByteChannel.buildFromLastSplitSegment(lastFile);
+ zf = new ZipFile(channel);
// the compressed content of ZipArchiveInputStream.java lies between .z01 and .z02
- ZipArchiveEntry zipEntry = zf.getEntry("main/java/org/apache/commons/compress/archivers/zip/ZipArchiveInputStream.java");
+ ZipArchiveEntry zipEntry = zf.getEntry("commons-compress/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveInputStream.java");
File fileToCompare = getFile("COMPRESS-477/split_zip_created_by_winrar/file_to_compare_1");
assertFileEqualsToEntry(fileToCompare, zipEntry, zf);
}
diff --git a/src/test/java/org/apache/commons/compress/utils/ZipSplitReadOnlySeekableByteChannelTest.java b/src/test/java/org/apache/commons/compress/utils/ZipSplitReadOnlySeekableByteChannelTest.java
index 4a36951..39c3029 100644
--- a/src/test/java/org/apache/commons/compress/utils/ZipSplitReadOnlySeekableByteChannelTest.java
+++ b/src/test/java/org/apache/commons/compress/utils/ZipSplitReadOnlySeekableByteChannelTest.java
@@ -18,6 +18,7 @@
package org.apache.commons.compress.utils;
+import org.apache.commons.compress.archivers.zip.ZipSplitReadOnlySeekableByteChannel;
import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test;
@@ -57,7 +58,7 @@ public class ZipSplitReadOnlySeekableByteChannelTest {
public void channelsPositionIsZeroAfterConstructor() throws IOException {
List<SeekableByteChannel> channels = getSplitZipChannels();
new ZipSplitReadOnlySeekableByteChannel(channels);
- for(SeekableByteChannel channel : channels) {
+ for (SeekableByteChannel channel : channels) {
Assert.assertEquals(0, channel.position());
}
}
@@ -142,19 +143,19 @@ public class ZipSplitReadOnlySeekableByteChannelTest {
@Test
public void positionToSomeZipSplitSegment() throws IOException {
File firstFile = getFile("COMPRESS-477/split_zip_created_by_zip/split_zip_created_by_zip.z01");
- int firstFileSize = (int)firstFile.length();
+ int firstFileSize = (int) firstFile.length();
File secondFile = getFile("COMPRESS-477/split_zip_created_by_zip/split_zip_created_by_zip.z02");
- int secondFileSize = (int)secondFile.length();
+ int secondFileSize = (int) secondFile.length();
File lastFile = getFile("COMPRESS-477/split_zip_created_by_zip/split_zip_created_by_zip.zip");
- int lastFileSize = (int)lastFile.length();
+ int lastFileSize = (int) lastFile.length();
Random random = new Random();
int randomDiskNumber = random.nextInt(3);
- int randomOffset = randomDiskNumber < 2 ? random.nextInt(firstFileSize):random.nextInt(lastFileSize);
+ int randomOffset = randomDiskNumber < 2 ? random.nextInt(firstFileSize) : random.nextInt(lastFileSize);
- ZipSplitReadOnlySeekableByteChannel channel = (ZipSplitReadOnlySeekableByteChannel)ZipSplitReadOnlySeekableByteChannel.buildFromLastSplitSegment(lastFile);
+ ZipSplitReadOnlySeekableByteChannel channel = (ZipSplitReadOnlySeekableByteChannel) ZipSplitReadOnlySeekableByteChannel.buildFromLastSplitSegment(lastFile);
channel.position(randomDiskNumber, randomOffset);
long expectedPosition = randomOffset;
diff --git a/src/test/resources/COMPRESS-477/split_zip_created_by_winrar/split_zip_created_by_winrar.z01 b/src/test/resources/COMPRESS-477/split_zip_created_by_winrar/split_zip_created_by_winrar.z01
index dc87d52..da153f7 100644
Binary files a/src/test/resources/COMPRESS-477/split_zip_created_by_winrar/split_zip_created_by_winrar.z01 and b/src/test/resources/COMPRESS-477/split_zip_created_by_winrar/split_zip_created_by_winrar.z01 differ
diff --git a/src/test/resources/COMPRESS-477/split_zip_created_by_winrar/split_zip_created_by_winrar.z02 b/src/test/resources/COMPRESS-477/split_zip_created_by_winrar/split_zip_created_by_winrar.z02
index 4fedb2f..e2047f4 100644
Binary files a/src/test/resources/COMPRESS-477/split_zip_created_by_winrar/split_zip_created_by_winrar.z02 and b/src/test/resources/COMPRESS-477/split_zip_created_by_winrar/split_zip_created_by_winrar.z02 differ
diff --git a/src/test/resources/COMPRESS-477/split_zip_created_by_winrar/split_zip_created_by_winrar.zip b/src/test/resources/COMPRESS-477/split_zip_created_by_winrar/split_zip_created_by_winrar.zip
index 6f10459..5937de8 100644
Binary files a/src/test/resources/COMPRESS-477/split_zip_created_by_winrar/split_zip_created_by_winrar.zip and b/src/test/resources/COMPRESS-477/split_zip_created_by_winrar/split_zip_created_by_winrar.zip differ
diff --git a/src/test/resources/COMPRESS-477/split_zip_created_by_winrar/zip_to_compare_created_by_winrar.zip b/src/test/resources/COMPRESS-477/split_zip_created_by_winrar/zip_to_compare_created_by_winrar.zip
new file mode 100644
index 0000000..a79bd67
Binary files /dev/null and b/src/test/resources/COMPRESS-477/split_zip_created_by_winrar/zip_to_compare_created_by_winrar.zip differ
diff --git a/src/test/resources/COMPRESS-477/split_zip_created_by_zip/zip_to_compare_created_by_zip.zip b/src/test/resources/COMPRESS-477/split_zip_created_by_zip/zip_to_compare_created_by_zip.zip
new file mode 100644
index 0000000..b7326ec
Binary files /dev/null and b/src/test/resources/COMPRESS-477/split_zip_created_by_zip/zip_to_compare_created_by_zip.zip differ
diff --git a/src/test/resources/COMPRESS-477/split_zip_created_by_zip/zip_to_compare_created_by_zip_zip64.zip b/src/test/resources/COMPRESS-477/split_zip_created_by_zip/zip_to_compare_created_by_zip_zip64.zip
new file mode 100644
index 0000000..f6cc080
Binary files /dev/null and b/src/test/resources/COMPRESS-477/split_zip_created_by_zip/zip_to_compare_created_by_zip_zip64.zip differ