Comment créer un fichier zip en Java

149

J'ai un fichier texte dynamique qui sélectionne le contenu d'une base de données en fonction de la requête de l'utilisateur. Je dois écrire ce contenu dans un fichier texte et le compresser dans un dossier dans un servlet. Comment dois-je faire cela?

Ashish Agarwal
la source

Réponses:

231

Regardez cet exemple:

StringBuilder sb = new StringBuilder();
sb.append("Test String");

File f = new File("d:\\test.zip");
ZipOutputStream out = new ZipOutputStream(new FileOutputStream(f));
ZipEntry e = new ZipEntry("mytext.txt");
out.putNextEntry(e);

byte[] data = sb.toString().getBytes();
out.write(data, 0, data.length);
out.closeEntry();

out.close();

Cela créera un zip à la racine de D:named test.zipqui contiendra un seul fichier appelé mytext.txt. Bien sûr, vous pouvez ajouter plus d'entrées zip et également spécifier un sous-répertoire comme celui-ci:

ZipEntry e = new ZipEntry("folderName/mytext.txt");

Vous pouvez trouver plus d'informations sur la compression avec Java ici .

Chris
la source
1
Pourquoi les deux lignes: sont-elles byte[] data = sb.toString().getBytes(); out.write(data, 0, data.length);incluses dans cet exemple de code? Quel est leur but?
Kaadzia
@kdzia, la première ligne convertit la valeur StringBuilder en un tableau d'octets, et la deuxième ligne prend ce tableau d'octets et l'écrit dans ZipEntry dans le fichier "test.zip". Ces lignes sont nécessaires car les fichiers Zip fonctionnent avec des tableaux d'octets, pas des chaînes.
OrangeWombat
3
Mais ... dans l'exemple ci-dessus, comment le StringBuilder contient-il autre chose que "Test String"? Je suis un peu confus par cela aussi. Si vous écrivez le sb.toString().getBytes()dans le fichier ZIP, je suppose que vous voudriez qu'il contienne les octets du fichier que vous zippez? Ou est-ce que je manque quelque chose?
RobA
3
@RobA vous ne manquez rien. Le StringBuilder est en effet destiné à contenir le texte que l'OP a obtenu de sa base de données. OP devrait simplement remplacer "Test String" (y compris les guillemets) par quelque chose comme getTextFromDatabase ()
Blueriver
Merci, @Blueriver
RobA
143

Java 7 intègre ZipFileSystem, qui peut être utilisé pour créer, écrire et lire un fichier à partir d'un fichier zip.

Doc Java: fournisseur ZipFileSystem

Map<String, String> env = new HashMap<>();
// Create the zip file if it doesn't exist
env.put("create", "true");

URI uri = URI.create("jar:file:/codeSamples/zipfs/zipfstest.zip");

try (FileSystem zipfs = FileSystems.newFileSystem(uri, env)) {
    Path externalTxtFile = Paths.get("/codeSamples/zipfs/SomeTextFile.txt");
    Path pathInZipfile = zipfs.getPath("/SomeTextFile.txt");          
    // Copy a file into the zip file
    Files.copy(externalTxtFile, pathInZipfile, StandardCopyOption.REPLACE_EXISTING); 
}
Sivabalan
la source
1
Existe-t-il un moyen de faire fonctionner cela si l'extension ne l'est pas .zip? J'ai besoin d'écrire un .foofichier, qui est formaté exactement comme un fichier zip, mais avec une extension différente. Je sais que je pourrais créer un .zipfichier et le renommer, mais le créer avec le bon nom serait plus simple.
Troy Daniels
2
@TroyDaniels l'exemple ci-dessus fonctionne également avec une extension différente, car il utilise le jar:file:préfixe pour créer l'URI.
Sivabalan
10
Le seul problème qui peut apparaître ici est que cela ne fonctionnera pas si vous avez des répertoires. Ainsi, par exemple, si vous avez "/dir/SomeTextFile.txt" dans la pathInZipfilevariable, vous devez créer le 'dir' dans l'archive .zip. Pour cela, ajoutez simplement la ligne suivante: Files.createDirectories(pathInZipfile.getParent())avant d'appeler la Files.copyméthode.
D. Naumovich
comment régler le niveau de compression?
cdalxndr
34

Pour écrire un fichier ZIP, vous utilisez un ZipOutputStream. Pour chaque entrée que vous souhaitez placer dans le fichier ZIP, vous créez un objet ZipEntry. Vous passez le nom de fichier au constructeur ZipEntry; il définit les autres paramètres tels que la date du fichier et la méthode de décompression. Vous pouvez remplacer ces paramètres si vous le souhaitez. Ensuite, vous appelez la méthode putNextEntry de ZipOutputStream pour commencer à écrire un nouveau fichier. Envoyez les données du fichier au flux ZIP. Lorsque vous avez terminé, appelez closeEntry. Répétez pour tous les fichiers que vous souhaitez stocker. Voici un squelette de code:

FileOutputStream fout = new FileOutputStream("test.zip");
ZipOutputStream zout = new ZipOutputStream(fout);
for all files
{
    ZipEntry ze = new ZipEntry(filename);
    zout.putNextEntry(ze);
    send data to zout;
    zout.closeEntry();
}
zout.close();
WiseGeek
la source
22

Voici un exemple de code pour compresser un répertoire entier (y compris les sous-fichiers et sous-répertoires), il utilise la fonctionnalité d'arborescence de fichiers de marche de Java NIO.

import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class ZipCompress {
    public static void compress(String dirPath) {
        final Path sourceDir = Paths.get(dirPath);
        String zipFileName = dirPath.concat(".zip");
        try {
            final ZipOutputStream outputStream = new ZipOutputStream(new FileOutputStream(zipFileName));
            Files.walkFileTree(sourceDir, new SimpleFileVisitor<Path>() {
                @Override
                public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) {
                    try {
                        Path targetFile = sourceDir.relativize(file);
                        outputStream.putNextEntry(new ZipEntry(targetFile.toString()));
                        byte[] bytes = Files.readAllBytes(file);
                        outputStream.write(bytes, 0, bytes.length);
                        outputStream.closeEntry();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    return FileVisitResult.CONTINUE;
                }
            });
            outputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Pour l'utiliser, il suffit d'appeler

ZipCompress.compress("target/directoryToCompress");

et vous obtiendrez un fichier zip directoryToCompress.zip

Owen Cao
la source
4

Contrôleur de démarrage Spring, compresser les fichiers dans un répertoire et peuvent être téléchargés.

@RequestMapping(value = "/files.zip")
@ResponseBody
byte[] filesZip() throws IOException {
    File dir = new File("./");
    File[] filesArray = dir.listFiles();
    if (filesArray == null || filesArray.length == 0)
        System.out.println(dir.getAbsolutePath() + " have no file!");
    ByteArrayOutputStream bo = new ByteArrayOutputStream();
    ZipOutputStream zipOut= new ZipOutputStream(bo);
    for(File xlsFile:filesArray){
        if(!xlsFile.isFile())continue;
        ZipEntry zipEntry = new ZipEntry(xlsFile.getName());
        zipOut.putNextEntry(zipEntry);
        zipOut.write(IOUtils.toByteArray(new FileInputStream(xlsFile)));
        zipOut.closeEntry();
    }
    zipOut.close();
    return bo.toByteArray();
}
Yuiffy
la source
2
public static void main(String args[])
{
    omtZip("res/", "omt.zip");
}
public static void omtZip(String path,String outputFile)
{
    final int BUFFER = 2048;
    boolean isEntry = false;
    ArrayList<String> directoryList = new ArrayList<String>();
    File f = new File(path);
    if(f.exists())
    {
    try {
            FileOutputStream fos = new FileOutputStream(outputFile);
            ZipOutputStream zos = new ZipOutputStream(new BufferedOutputStream(fos));
            byte data[] = new byte[BUFFER];

            if(f.isDirectory())
            {
               //This is Directory
                do{
                    String directoryName = "";
                    if(directoryList.size() > 0)
                    {
                        directoryName = directoryList.get(0);
                        System.out.println("Directory Name At 0 :"+directoryName);
                    }
                    String fullPath = path+directoryName;
                    File fileList = null;
                    if(directoryList.size() == 0)
                    {
                        //Main path (Root Directory)
                        fileList = f;
                    }else
                    {
                        //Child Directory
                        fileList = new File(fullPath);
                    }
                    String[] filesName = fileList.list();

                    int totalFiles = filesName.length;
                    for(int i = 0 ; i < totalFiles ; i++)
                    {
                        String name = filesName[i];
                        File filesOrDir = new File(fullPath+name);
                        if(filesOrDir.isDirectory())
                        {
                            System.out.println("New Directory Entry :"+directoryName+name+"/");
                            ZipEntry entry = new ZipEntry(directoryName+name+"/");
                            zos.putNextEntry(entry);
                            isEntry = true;
                            directoryList.add(directoryName+name+"/");
                        }else
                        {
                            System.out.println("New File Entry :"+directoryName+name);
                            ZipEntry entry = new ZipEntry(directoryName+name);
                            zos.putNextEntry(entry);
                            isEntry = true;
                            FileInputStream fileInputStream = new FileInputStream(filesOrDir);
                            BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream, BUFFER);
                            int size = -1;
                            while(  (size = bufferedInputStream.read(data, 0, BUFFER)) != -1  )
                            {
                                zos.write(data, 0, size);
                            }
                            bufferedInputStream.close();
                        }
                    }
                    if(directoryList.size() > 0 && directoryName.trim().length() > 0)
                    {
                        System.out.println("Directory removed :"+directoryName);
                        directoryList.remove(0);
                    }

                }while(directoryList.size() > 0);
            }else
            {
                //This is File
                //Zip this file
                System.out.println("Zip this file :"+f.getPath());
                FileInputStream fis = new FileInputStream(f);
                BufferedInputStream bis = new BufferedInputStream(fis,BUFFER);
                ZipEntry entry = new ZipEntry(f.getName());
                zos.putNextEntry(entry);
                isEntry = true;
                int size = -1 ;
                while(( size = bis.read(data,0,BUFFER)) != -1)
                {
                    zos.write(data, 0, size);
                }
            }               

            //CHECK IS THERE ANY ENTRY IN ZIP ? ----START
            if(isEntry)
            {
              zos.close();
            }else
            {
                zos = null;
                System.out.println("No Entry Found in Zip");
            }
            //CHECK IS THERE ANY ENTRY IN ZIP ? ----START
        }catch(Exception e)
        {
            e.printStackTrace();
        }
    }else
    {
        System.out.println("File or Directory not found");
    }
 }    

}
Dhiral Pandya
la source
2

Voici comment créer un fichier zip à partir d'un fichier source:

String srcFilename = "C:/myfile.txt";
String zipFile = "C:/myfile.zip";

try {
    byte[] buffer = new byte[1024];
    FileOutputStream fos = new FileOutputStream(zipFile);
    ZipOutputStream zos = new ZipOutputStream(fos);         
    File srcFile = new File(srcFilename);
    FileInputStream fis = new FileInputStream(srcFile);
    zos.putNextEntry(new ZipEntry(srcFile.getName()));          
    int length;
    while ((length = fis.read(buffer)) > 0) {
        zos.write(buffer, 0, length);
    }
    zos.closeEntry();
    fis.close();
    zos.close();            
}
catch (IOException ioe) {
    System.out.println("Error creating zip file" + ioe);
}
l'amour en direct
la source
1

Un seul fichier:

String filePath = "/absolute/path/file1.txt";
String zipPath = "/absolute/path/output.zip";

try (ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(zipPath))) {
    File fileToZip = new File(filePath);
    zipOut.putNextEntry(new ZipEntry(fileToZip.getName()));
    Files.copy(fileToZip.toPath(), zipOut);
}

Plusieurs fichiers:

List<String> filePaths = Arrays.asList("/absolute/path/file1.txt", "/absolute/path/file2.txt");
String zipPath = "/absolute/path/output.zip";

try (ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(zipPath))) {
    for (String filePath : filePaths) {
        File fileToZip = new File(filePath);
        zipOut.putNextEntry(new ZipEntry(fileToZip.getName()));
        Files.copy(fileToZip.toPath(), zipOut);
    }
}
Pavel
la source
1

Vous devez principalement créer deux fonctions. Le premier est writeToZipFile () et le second est createZipfileForOutPut .... puis appelez le createZipfileForOutPut ('nom de fichier .zip') `...

 public static void writeToZipFile(String path, ZipOutputStream zipStream)
        throws FileNotFoundException, IOException {

    System.out.println("Writing file : '" + path + "' to zip file");

    File aFile = new File(path);
    FileInputStream fis = new FileInputStream(aFile);
    ZipEntry zipEntry = new ZipEntry(path);
    zipStream.putNextEntry(zipEntry);

    byte[] bytes = new byte[1024];
    int length;
    while ((length = fis.read(bytes)) >= 0) {
        zipStream.write(bytes, 0, length);
    }

    zipStream.closeEntry();
    fis.close();
}

public static void createZipfileForOutPut(String filename) {
    String home = System.getProperty("user.home");
   // File directory = new File(home + "/Documents/" + "AutomationReport");
    File directory = new File("AutomationReport");
    if (!directory.exists()) {
        directory.mkdir();
    }
    try {
        FileOutputStream fos = new FileOutputStream("Path to your destination" + filename + ".zip");
        ZipOutputStream zos = new ZipOutputStream(fos);

        writeToZipFile("Path to file which you want to compress / zip", zos);


        zos.close();
        fos.close();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}
Tarpan Patel
la source
0

Si vous voulez décompresser sans logiciel, utilisez mieux ce code. Un autre code avec des fichiers pdf envoie une erreur lors de la décompression manuelle

byte[] buffer = new byte[1024];     
    try
    {   
        FileOutputStream fos = new FileOutputStream("123.zip");
        ZipOutputStream zos = new ZipOutputStream(fos);
        ZipEntry ze= new ZipEntry("file.pdf");
        zos.putNextEntry(ze);
        FileInputStream in = new FileInputStream("file.pdf");
        int len;
        while ((len = in.read(buffer)) > 0) 
        {
            zos.write(buffer, 0, len);
        }
        in.close();
        zos.closeEntry();
        zos.close();
    }
    catch(IOException ex)
    {
       ex.printStackTrace();
    }
cmujica
la source
0

Comme il m'a fallu un certain temps pour le comprendre, j'ai pensé qu'il serait utile de publier ma solution en utilisant Java 7+ ZipFileSystem

 openZip(runFile);

 addToZip(filepath); //loop construct;  

 zipfs.close();

 private void openZip(File runFile) throws IOException {
    Map<String, String> env = new HashMap<>();
    env.put("create", "true");
    env.put("encoding", "UTF-8");
    Files.deleteIfExists(runFile.toPath());
    zipfs = FileSystems.newFileSystem(URI.create("jar:" + runFile.toURI().toString()), env);    
 }

 private void addToZip(String filename) throws IOException {
    Path externalTxtFile = Paths.get(filename).toAbsolutePath();
    Path pathInZipfile = zipfs.getPath(filename.substring(filename.lastIndexOf("results"))); //all files to be stored have a common base folder, results/ in my case
    if (Files.isDirectory(externalTxtFile)) {
        Files.createDirectories(pathInZipfile);
        try (DirectoryStream<Path> ds = Files.newDirectoryStream(externalTxtFile)) {
            for (Path child : ds) {
                addToZip(child.normalize().toString()); //recursive call
            }
        }
    } else {
        // copy file to zip file
        Files.copy(externalTxtFile, pathInZipfile, StandardCopyOption.REPLACE_EXISTING);            
    }
 }
Siraj K
la source
0
public static void zipFromTxt(String zipFilePath, String txtFilePath) {
    Assert.notNull(zipFilePath, "Zip file path is required");
    Assert.notNull(txtFilePath, "Txt file path is required");
    zipFromTxt(new File(zipFilePath), new File(txtFilePath));
}

public static void zipFromTxt(File zipFile, File txtFile) {
    ZipOutputStream out = null;
    FileInputStream in = null;
    try {
        Assert.notNull(zipFile, "Zip file is required");
        Assert.notNull(txtFile, "Txt file is required");
        out = new ZipOutputStream(new FileOutputStream(zipFile));
        in = new FileInputStream(txtFile);
        out.putNextEntry(new ZipEntry(txtFile.getName()));
        int len;
        byte[] buffer = new byte[1024];
        while ((len = in.read(buffer)) > 0) {
            out.write(buffer, 0, len);
            out.flush();
        }
    } catch (Exception e) {
        log.info("Zip from txt occur error,Detail message:{}", e.toString());
    } finally {
        try {
            if (in != null) in.close();
            if (out != null) {
                out.closeEntry();
                out.close();
            }
        } catch (Exception e) {
            log.info("Zip from txt close error,Detail message:{}", e.toString());
        }
    }
}
鄒成立
la source
0

Étant donné exportPathet en queryResultstant que variables String, le bloc suivant crée un results.zipfichier sous exportPathet écrit le contenu de queryResultsdans un results.txtfichier à l'intérieur du zip.

URI uri = URI.create("jar:file:" + exportPath + "/results.zip");
Map<String, String> env = Collections.singletonMap("create", "true");

try (FileSystem zipfs = FileSystems.newFileSystem(uri, env)) {
  Path filePath = zipfs.getPath("/results.txt");
  byte[] fileContent = queryResults.getBytes();

  Files.write(filePath, fileContent, StandardOpenOption.CREATE);
}
Camilo Silva
la source
0

En utilisant Jeka https://jeka.dev JkPathTree, c'est assez simple.

Path wholeDirToZip = Paths.get("dir/to/zip");
Path zipFile = Paths.get("file.zip");
JkPathTree.of(wholeDirToZip).zipTo(zipFile);
Jérôme Angibaud
la source
0

Il existe une autre option en utilisant zip4jà https://github.com/srikanth-lingala/zip4j

Création d'un fichier zip avec un seul fichier / Ajout d'un seul fichier à un zip existant

new ZipFile("filename.zip").addFile("filename.ext"); Ou

new ZipFile("filename.zip").addFile(new File("filename.ext"));

Créer un fichier zip avec plusieurs fichiers / Ajouter plusieurs fichiers à un zip existant

new ZipFile("filename.zip").addFiles(Arrays.asList(new File("first_file"), new File("second_file")));

Créer un fichier zip en y ajoutant un dossier / Ajouter un dossier à un zip existant

new ZipFile("filename.zip").addFolder(new File("/user/myuser/folder_to_add"));

Créer un fichier zip à partir d'un flux / Ajouter un flux à un zip existant new ZipFile("filename.zip").addStream(inputStream, new ZipParameters());

sendon1982
la source