J'ai un fichier Zip qui contient d'autres fichiers Zip.
Par exemple, le fichier courrier est abc.Zip
et il contient xyz.Zip
, class1.Java
, class2.Java
. Et xyz.Zip
contient le fichier class3.Java
et class4.Java
.
J'ai donc besoin d'extraire le fichier Zip en utilisant Java dans un dossier qui devrait contenir class1.Java
, class2.Java
, class3.Java
et class4.Java
.
Attention, le code ici est correct pour les fichiers Zip de confiance, il n'y a pas de validation de chemin avant l'écriture qui peut conduire à une vulnérabilité de sécurité comme décrit dans Zip-slip-vulnérabilité si vous l'utilisez pour dégonfler un fichier Zip téléchargé de client inconnu.
Cette solution est très similaire aux solutions précédentes déjà publiées, mais celle-ci recrée la bonne structure de dossiers lors de la décompression.
static public void extractFolder(String zipFile) throws ZipException, IOException
{
System.out.println(zipFile);
int BUFFER = 2048;
File file = new File(zipFile);
ZipFile Zip = new ZipFile(file);
String newPath = zipFile.substring(0, zipFile.length() - 4);
new File(newPath).mkdir();
Enumeration zipFileEntries = Zip.entries();
// Process each entry
while (zipFileEntries.hasMoreElements())
{
// grab a Zip file entry
ZipEntry entry = (ZipEntry) zipFileEntries.nextElement();
String currentEntry = entry.getName();
File destFile = new File(newPath, currentEntry);
//destFile = new File(newPath, destFile.getName());
File destinationParent = destFile.getParentFile();
// create the parent directory structure if needed
destinationParent.mkdirs();
if (!entry.isDirectory())
{
BufferedInputStream is = new BufferedInputStream(Zip
.getInputStream(entry));
int currentByte;
// establish buffer for writing file
byte data[] = new byte[BUFFER];
// write the current file to disk
FileOutputStream fos = new FileOutputStream(destFile);
BufferedOutputStream dest = new BufferedOutputStream(fos,
BUFFER);
// read and write until last byte is encountered
while ((currentByte = is.read(data, 0, BUFFER)) != -1) {
dest.write(data, 0, currentByte);
}
dest.flush();
dest.close();
is.close();
}
if (currentEntry.endsWith(".Zip"))
{
// found a Zip file, try to open
extractFolder(destFile.getAbsolutePath());
}
}
}
Voici une base de code non testée sur un ancien code que j'avais des fichiers décompressés.
public void doUnzip(String inputZip, String destinationDirectory)
throws IOException {
int BUFFER = 2048;
List zipFiles = new ArrayList();
File sourceZipFile = new File(inputZip);
File unzipDestinationDirectory = new File(destinationDirectory);
unzipDestinationDirectory.mkdir();
ZipFile zipFile;
// Open Zip file for reading
zipFile = new ZipFile(sourceZipFile, ZipFile.OPEN_READ);
// Create an enumeration of the entries in the Zip file
Enumeration zipFileEntries = zipFile.entries();
// Process each entry
while (zipFileEntries.hasMoreElements()) {
// grab a Zip file entry
ZipEntry entry = (ZipEntry) zipFileEntries.nextElement();
String currentEntry = entry.getName();
File destFile = new File(unzipDestinationDirectory, currentEntry);
destFile = new File(unzipDestinationDirectory, destFile.getName());
if (currentEntry.endsWith(".Zip")) {
zipFiles.add(destFile.getAbsolutePath());
}
// grab file's parent directory structure
File destinationParent = destFile.getParentFile();
// create the parent directory structure if needed
destinationParent.mkdirs();
try {
// extract file if not a directory
if (!entry.isDirectory()) {
BufferedInputStream is =
new BufferedInputStream(zipFile.getInputStream(entry));
int currentByte;
// establish buffer for writing file
byte data[] = new byte[BUFFER];
// write the current file to disk
FileOutputStream fos = new FileOutputStream(destFile);
BufferedOutputStream dest =
new BufferedOutputStream(fos, BUFFER);
// read and write until last byte is encountered
while ((currentByte = is.read(data, 0, BUFFER)) != -1) {
dest.write(data, 0, currentByte);
}
dest.flush();
dest.close();
is.close();
}
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
zipFile.close();
for (Iterator iter = zipFiles.iterator(); iter.hasNext();) {
String zipName = (String)iter.next();
doUnzip(
zipName,
destinationDirectory +
File.separatorChar +
zipName.substring(0,zipName.lastIndexOf(".Zip"))
);
}
}
Je prends ca.anderson4 et supprime la liste des fichiers zip et réécris un peu, voici ce que j'ai obtenu:
public class Unzip {
public void unzip(String zipFile) throws ZipException,
IOException {
System.out.println(zipFile);;
int BUFFER = 2048;
File file = new File(zipFile);
ZipFile Zip = new ZipFile(file);
String newPath = zipFile.substring(0, zipFile.length() - 4);
new File(newPath).mkdir();
Enumeration zipFileEntries = Zip.entries();
// Process each entry
while (zipFileEntries.hasMoreElements()) {
// grab a Zip file entry
ZipEntry entry = (ZipEntry) zipFileEntries.nextElement();
String currentEntry = entry.getName();
File destFile = new File(newPath, currentEntry);
destFile = new File(newPath, destFile.getName());
File destinationParent = destFile.getParentFile();
// create the parent directory structure if needed
destinationParent.mkdirs();
if (!entry.isDirectory()) {
BufferedInputStream is = new BufferedInputStream(Zip
.getInputStream(entry));
int currentByte;
// establish buffer for writing file
byte data[] = new byte[BUFFER];
// write the current file to disk
FileOutputStream fos = new FileOutputStream(destFile);
BufferedOutputStream dest = new BufferedOutputStream(fos,
BUFFER);
// read and write until last byte is encountered
while ((currentByte = is.read(data, 0, BUFFER)) != -1) {
dest.write(data, 0, currentByte);
}
dest.flush();
dest.close();
is.close();
}
if (currentEntry.endsWith(".Zip")) {
// found a Zip file, try to open
unzip(destFile.getAbsolutePath());
}
}
}
public static void main(String[] args) {
Unzip unzipper=new Unzip();
try {
unzipper.unzip("test/test.Zip");
} catch (ZipException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
J'ai testé et ça marche
Modifié selon mes besoins, puis mélangé à quelques-unes des meilleures réponses. Cette version:
Extraire récursivement un Zip à un emplacement donné
Créer des répertoires vides
Fermer correctement Zip
public static void unZipAll(File source, File destination) throws IOException
{
System.out.println("Unzipping - " + source.getName());
int BUFFER = 2048;
ZipFile Zip = new ZipFile(source);
try{
destination.getParentFile().mkdirs();
Enumeration zipFileEntries = Zip.entries();
// Process each entry
while (zipFileEntries.hasMoreElements())
{
// grab a Zip file entry
ZipEntry entry = (ZipEntry) zipFileEntries.nextElement();
String currentEntry = entry.getName();
File destFile = new File(destination, currentEntry);
//destFile = new File(newPath, destFile.getName());
File destinationParent = destFile.getParentFile();
// create the parent directory structure if needed
destinationParent.mkdirs();
if (!entry.isDirectory())
{
BufferedInputStream is = null;
FileOutputStream fos = null;
BufferedOutputStream dest = null;
try{
is = new BufferedInputStream(Zip.getInputStream(entry));
int currentByte;
// establish buffer for writing file
byte data[] = new byte[BUFFER];
// write the current file to disk
fos = new FileOutputStream(destFile);
dest = new BufferedOutputStream(fos, BUFFER);
// read and write until last byte is encountered
while ((currentByte = is.read(data, 0, BUFFER)) != -1) {
dest.write(data, 0, currentByte);
}
} catch (Exception e){
System.out.println("unable to extract entry:" + entry.getName());
throw e;
} finally{
if (dest != null){
dest.close();
}
if (fos != null){
fos.close();
}
if (is != null){
is.close();
}
}
}else{
//Create directory
destFile.mkdirs();
}
if (currentEntry.endsWith(".Zip"))
{
// found a Zip file, try to extract
unZipAll(destFile, destinationParent);
if(!destFile.delete()){
System.out.println("Could not delete Zip");
}
}
}
} catch(Exception e){
e.printStackTrace();
System.out.println("Failed to successfully unzip:" + source.getName());
} finally {
Zip.close();
}
System.out.println("Done Unzipping:" + source.getName());
}
Lors des tests, j'ai remarqué que File.mkDirs () ne fonctionne pas sous Windows ...
/ ** * pour un nom de chemin complet donné recrée tous les répertoires parents ** /
private void createParentHierarchy(String parentName) throws IOException {
File parent = new File(parentName);
String[] parentsStrArr = parent.getAbsolutePath().split(File.separator == "/" ? "/" : "\\\\");
//create the parents of the parent
for(int i=0; i < parentsStrArr.length; i++){
StringBuffer currParentPath = new StringBuffer();
for(int j = 0; j < i; j++){
currParentPath.append(parentsStrArr[j]+File.separator);
}
File currParent = new File(currParentPath.toString());
if(!currParent.isDirectory()){
boolean created = currParent.mkdir();
if(isVerbose)log("creating directory "+currParent.getAbsolutePath());
}
}
//create the parent itself
if(!parent.isDirectory()){
boolean success = parent.mkdir();
}
}
On devrait FERMER le fichier Zip après décompresser.
static public void extractFolder(String zipFile) throws ZipException, IOException
{
System.out.println(zipFile);
int BUFFER = 2048;
File file = new File(zipFile);
ZipFile Zip = new ZipFile(file);
try
{
...code from other answers ( ex. NeilMonday )...
}
finally
{
Zip.close();
}
}
Identique à la réponse de NeilMonday, mais extrait les répertoires vides:
static public void extractFolder(String zipFile) throws ZipException, IOException
{
System.out.println(zipFile);
int BUFFER = 2048;
File file = new File(zipFile);
ZipFile Zip = new ZipFile(file);
String newPath = zipFile.substring(0, zipFile.length() - 4);
new File(newPath).mkdir();
Enumeration zipFileEntries = Zip.entries();
// Process each entry
while (zipFileEntries.hasMoreElements())
{
// grab a Zip file entry
ZipEntry entry = (ZipEntry) zipFileEntries.nextElement();
String currentEntry = entry.getName();
File destFile = new File(newPath, currentEntry);
//destFile = new File(newPath, destFile.getName());
File destinationParent = destFile.getParentFile();
// create the parent directory structure if needed
destinationParent.mkdirs();
if (!entry.isDirectory())
{
BufferedInputStream is = new BufferedInputStream(Zip
.getInputStream(entry));
int currentByte;
// establish buffer for writing file
byte data[] = new byte[BUFFER];
// write the current file to disk
FileOutputStream fos = new FileOutputStream(destFile);
BufferedOutputStream dest = new BufferedOutputStream(fos,
BUFFER);
// read and write until last byte is encountered
while ((currentByte = is.read(data, 0, BUFFER)) != -1) {
dest.write(data, 0, currentByte);
}
dest.flush();
dest.close();
is.close();
}
else{
destFile.mkdirs()
}
if (currentEntry.endsWith(".Zip"))
{
// found a Zip file, try to open
extractFolder(destFile.getAbsolutePath());
}
}
}