-
Notifications
You must be signed in to change notification settings - Fork 273
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
COMPRESS-692: Add support for zstd compression in zip archives #634
Closed
mehmet-karaman
wants to merge
1
commit into
apache:master
from
mehmet-karaman:implemented_zstd_support
Closed
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,7 +18,13 @@ | |
*/ | ||
package org.apache.commons.compress.compressors.zstandard; | ||
|
||
import java.io.IOException; | ||
import java.io.InputStream; | ||
import java.io.OutputStream; | ||
|
||
import org.apache.commons.compress.utils.OsgiUtils; | ||
import org.apache.commons.io.IOUtils; | ||
import org.apache.commons.io.output.CountingOutputStream; | ||
|
||
/** | ||
* Utility code for the Zstandard compression format. | ||
|
@@ -28,6 +34,23 @@ | |
*/ | ||
public class ZstdUtils { | ||
|
||
private static final class InnerNotClosingOutputStream extends CountingOutputStream { | ||
mehmet-karaman marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
/** | ||
* The close of this class wont close its delegated output stream. | ||
* | ||
* @param delegate the output stream to which the output will be delegated | ||
*/ | ||
private InnerNotClosingOutputStream(OutputStream delegate) { | ||
super(delegate); | ||
} | ||
|
||
@Override | ||
public void close() throws IOException { | ||
// Don't close the inner output stream. | ||
} | ||
} | ||
|
||
enum CachedAvailability { | ||
DONT_CACHE, CACHED_AVAILABLE, CACHED_UNAVAILABLE | ||
} | ||
|
@@ -134,4 +157,21 @@ public static void setCacheZstdAvailablity(final boolean doCache) { | |
/** Private constructor to prevent instantiation of this utility class. */ | ||
private ZstdUtils() { | ||
} | ||
|
||
/** | ||
* Reads uncompressed data stream and writes it compressed to the output | ||
* | ||
* @param input the data stream with uncompressed data | ||
* @param output the data stream for compressed output | ||
* @return the compressed size | ||
* @throws IOException throws the exception which could be got from from IOUtils.copyLarge() | ||
* or ZstdCompressorOutputStream constructor | ||
*/ | ||
public static long readAndCompressWrite(InputStream input, OutputStream output) throws IOException { | ||
mehmet-karaman marked this conversation as resolved.
Show resolved
Hide resolved
|
||
final InnerNotClosingOutputStream outStream = new InnerNotClosingOutputStream(output); | ||
final ZstdCompressorOutputStream outputStream = new ZstdCompressorOutputStream(outStream, 3, true); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The value |
||
IOUtils.copyLarge(input, outputStream); | ||
outputStream.flush(); | ||
return outStream.getByteCount(); | ||
} | ||
} |
142 changes: 142 additions & 0 deletions
142
src/test/java/org/apache/commons/compress/archivers/zip/ZstdCompressorTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
/* | ||
* 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 | ||
* | ||
* https://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.archivers.zip; | ||
|
||
import static org.junit.Assert.assertEquals; | ||
import static org.junit.Assert.assertTrue; | ||
|
||
import java.io.ByteArrayInputStream; | ||
import java.io.File; | ||
import java.io.FileInputStream; | ||
import java.io.IOException; | ||
import java.io.InputStream; | ||
import java.nio.file.Files; | ||
import java.nio.file.Path; | ||
|
||
import org.apache.commons.compress.AbstractTest; | ||
import org.apache.commons.compress.compressors.zstandard.ZstdCompressorInputStream; | ||
import org.apache.commons.compress.compressors.zstandard.ZstdUtils; | ||
import org.junit.jupiter.api.Test; | ||
|
||
public class ZstdCompressorTest extends AbstractTest { | ||
|
||
@Test | ||
public void testZstdInputStream() throws IOException { | ||
final Path file = getPath("COMPRESS-692/compress-962.zip"); | ||
mehmet-karaman marked this conversation as resolved.
Show resolved
Hide resolved
|
||
try (ZipFile zip = ZipFile.builder().setFile(file.toFile()).get()) { | ||
final ZipArchiveEntry entry = zip.getEntries().nextElement(); | ||
assertEquals("Unexpected first entry", "dolor.txt", entry.getName()); | ||
assertTrue("entry can't be read", zip.canReadEntryData(entry)); | ||
assertEquals("Unexpected method", ZipMethod.ZSTD.getCode(), entry.getMethod()); | ||
|
||
try (InputStream inputStream = zip.getInputStream(entry)) { | ||
final long uncompSize = entry.getSize(); | ||
final byte[] buf = new byte[(int) uncompSize]; | ||
inputStream.read(buf); | ||
|
||
final String uncompData = new String(buf); | ||
assertTrue(uncompData.startsWith("dolor sit amet")); | ||
assertTrue(uncompData.endsWith("ex ea commodo")); | ||
assertEquals(6066, uncompData.length()); | ||
} | ||
|
||
} | ||
} | ||
|
||
@Test | ||
public void testZstdMethodInZipFile() throws IOException { | ||
final String zipContentFile = "Name.txt"; | ||
final byte[] simpleText = "This is a Simple Test File.".getBytes(); | ||
final File file = Files.createTempFile("", ".zip").toFile(); | ||
// Create the Zip File | ||
{ | ||
try (ZipArchiveOutputStream zipOutputStream = new ZipArchiveOutputStream(file)) { | ||
final ZipArchiveEntry archiveEntry = new ZipArchiveEntry(zipContentFile); | ||
archiveEntry.setMethod(ZipMethod.ZSTD.getCode()); | ||
archiveEntry.setSize(simpleText.length); | ||
zipOutputStream.putArchiveEntry(archiveEntry); | ||
ZstdUtils.readAndCompressWrite(new ByteArrayInputStream(simpleText), zipOutputStream); | ||
zipOutputStream.closeArchiveEntry(); | ||
} | ||
} | ||
|
||
// Read the Zip File | ||
{ | ||
try (ZipFile zipFile = ZipFile.builder().setFile(file).get()) { | ||
// Find the entry | ||
final ZipArchiveEntry entry = zipFile.getEntry(zipContentFile); | ||
|
||
// Check the Zstd compression method | ||
assertEquals(entry.getMethod(), ZipMethod.ZSTD.getCode()); | ||
final InputStream inputStream = zipFile.getInputStream(entry); | ||
assertTrue(inputStream instanceof ZstdCompressorInputStream); | ||
|
||
final long dataOffset = entry.getDataOffset(); | ||
final int uncompressedSize = (int) entry.getSize(); | ||
|
||
assertEquals(simpleText.length, uncompressedSize); | ||
|
||
final byte[] uncompressedData = new byte[uncompressedSize]; | ||
inputStream.read(uncompressedData, 0, uncompressedSize); | ||
|
||
// Check the uncompressed data | ||
assertEquals(new String(simpleText), new String(uncompressedData)); | ||
|
||
try (FileInputStream fileInputStream = new FileInputStream(file)) { | ||
fileInputStream.skip(dataOffset); | ||
final byte[] compressedData = new byte[4]; | ||
fileInputStream.read(compressedData); | ||
assertTrue("Compressed data must begin with the magic bytes of Zstd", ZstdUtils.matches(compressedData, 4)); | ||
} | ||
} | ||
} | ||
} | ||
|
||
@Test | ||
public void testZstdDeprecatedMethod() throws IOException { | ||
final String zipContentFile = "Name.txt"; | ||
final byte[] simpleText = "This is a Simple Test File.".getBytes(); | ||
final File file = Files.createTempFile("", ".zip").toFile(); | ||
// Create the Zip File | ||
{ | ||
try (ZipArchiveOutputStream zipOutputStream = new ZipArchiveOutputStream(file)) { | ||
final ZipArchiveEntry archiveEntry = new ZipArchiveEntry(zipContentFile); | ||
archiveEntry.setMethod(ZipMethod.ZSTD_DEPRECATED.getCode()); | ||
archiveEntry.setSize(simpleText.length); | ||
zipOutputStream.putArchiveEntry(archiveEntry); | ||
ZstdUtils.readAndCompressWrite(new ByteArrayInputStream(simpleText), zipOutputStream); | ||
zipOutputStream.closeArchiveEntry(); | ||
} | ||
} | ||
|
||
// Read the Zip File | ||
{ | ||
try (ZipFile zipFile = ZipFile.builder().setFile(file).get()) { | ||
// Find the entry | ||
final ZipArchiveEntry entry = zipFile.getEntry(zipContentFile); | ||
|
||
// Check the Zstd compression method | ||
assertEquals(entry.getMethod(), ZipMethod.ZSTD_DEPRECATED.getCode()); | ||
final InputStream inputStream = zipFile.getInputStream(entry); | ||
|
||
assertTrue("Input stream must be a ZstdInputStream", inputStream instanceof ZstdCompressorInputStream); | ||
} | ||
} | ||
} | ||
} |
Binary file not shown.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not needed, removed in git master.