Created
August 13, 2018 09:24
-
-
Save cbonesana/be5775653af51ce47a539ef421a62ec7 to your computer and use it in GitHub Desktop.
Just an example to solve the issue of opening a zip archive containing multiples zip archives, without enough space to extract everything on the disk first.
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
<?xml version="1.0" encoding="UTF-8"?> | |
<project xmlns="http://maven.apache.org/POM/4.0.0" | |
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | |
<modelVersion>4.0.0</modelVersion> | |
<groupId>test</groupId> | |
<artifactId>nested-zip</artifactId> | |
<version>1.0-SNAPSHOT</version> | |
<build> | |
<plugins> | |
<plugin> | |
<groupId>org.apache.maven.plugins</groupId> | |
<artifactId>maven-compiler-plugin</artifactId> | |
<configuration> | |
<source>8</source> | |
<target>8</target> | |
</configuration> | |
</plugin> | |
</plugins> | |
</build> | |
<dependencies> | |
<!-- Manipulate the jsons --> | |
<dependency> | |
<groupId>org.json</groupId> | |
<artifactId>json</artifactId> | |
<version>20180130</version> | |
</dependency> | |
<!-- Log4j2 as logger --> | |
<dependency> | |
<groupId>org.apache.logging.log4j</groupId> | |
<artifactId>log4j-api</artifactId> | |
<version>2.11.1</version> | |
</dependency> | |
<dependency> | |
<groupId>org.apache.logging.log4j</groupId> | |
<artifactId>log4j-core</artifactId> | |
<version>2.11.1</version> | |
</dependency> | |
</dependencies> | |
</project> |
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
import org.apache.logging.log4j.LogManager; | |
import org.apache.logging.log4j.Logger; | |
import org.json.JSONArray; | |
import org.json.JSONObject; | |
import java.io.*; | |
import java.util.zip.ZipEntry; | |
import java.util.zip.ZipInputStream; | |
/** | |
* Author: Claudio "Dna" Bonesana | |
* Date: 13.08.2018 08:46 | |
* Project: nested-zip | |
*/ | |
public class ZipInZipApplication { | |
private static final Logger log = LogManager.getLogger(ZipInZipApplication.class); | |
/* | |
* This is a zip with the following: content: | |
* - first | |
* - example.zip | |
* - example.json | |
* - second.zip | |
* - second | |
* - example.json | |
* | |
* The json files are the same. | |
*/ | |
private static final String filename = "nested.zip"; | |
public static void main(String[] args) { | |
/* | |
* The idea of this code is to extract the content of a Zip archive inside a Zip archive without extract them. | |
*/ | |
try ( | |
// stream data from the input file | |
InputStream fis = new FileInputStream(filename); | |
// bufferize the input | |
BufferedInputStream bis = new BufferedInputStream(fis); | |
// convert the reader as a zip input stream so we can manipulate the content | |
ZipInputStream zis = new ZipInputStream(bis) | |
) { | |
ZipEntry ze; | |
// loop over all the entries in the first zip file | |
while ((ze = zis.getNextEntry()) != null) { | |
// get some information from the current ZipEntry | |
String name = ze.getName(); | |
long compressedSize = ze.getCompressedSize(); | |
long size = ze.getSize(); | |
log.info(String.format("%-32s %10d %10d", name, compressedSize, size)); | |
// if we have a nested zip, open it | |
if (name.endsWith("zip")) { | |
/* | |
When we use the getNextEntry() method, we move a cursors inside the ZipInputStream, this let us | |
explore all the directory tree by just wrap the current stream around a new ZipInputStream. | |
This solution was adapted from: | |
https://stackoverflow.com/a/47209656/1419058 | |
*/ | |
ZipInputStream zisIn = new ZipInputStream(zis); | |
ZipEntry zeIn; | |
while ((zeIn = zisIn.getNextEntry()) != null) { | |
// we are now in the internal zip | |
String nameIn = zeIn.getName(); | |
log.info(" --> " + nameIn); | |
if (nameIn.endsWith(".json")) { | |
// if it is a file that we want to extract some data from, we use a BufferedReader to do so | |
Reader isr = new InputStreamReader(zisIn); | |
BufferedReader br = new BufferedReader(isr); | |
String line; | |
while ((line = br.readLine()) != null) { | |
// ...then convert it to a JSON object and do magic stuff | |
final JSONObject jo = new JSONObject(line); | |
String startTime = jo.getString("startTime"); | |
int duration = jo.getInt("duration"); | |
JSONArray trackpoints = jo.getJSONArray("trackpoints"); | |
log.info(" : " + startTime); | |
log.info(" : " + duration); | |
log.info(" : " + trackpoints.length()); | |
} | |
/* | |
Note that we are not using try-catch-resource there. If we use this syntax, the main | |
InputStream (zis) will also be closed because we are wrapping always the same stream! | |
Uncomment the following line to generate such error. | |
*/ | |
// br.close(); | |
} | |
} | |
} | |
} | |
} catch (IOException e) { | |
log.error("Generic IOException", e); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment