2009-07-07 10 views
81

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 une servlet. Comment dois-je faire cela?Comment créer un fichier zip en Java

Répondre

136

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 va créer un fichier ZIP situé à la racine de D: nommé « test.zip » qui 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:

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

Vous pouvez trouver plus d'informations sur la compression avec java ici:

http://www.oracle.com/technetwork/articles/java/compress-1565076.html

+0

Pourquoi les deux lignes: 'octet [] = données sb.ToString () .getBytes(); out.write (data, 0, data.length); 'inclus dans cet exemple de code? Quel est leur but? – Kaadzia

+0

@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 le ZipEntry dans le fichier "test.zip". Ces lignes sont nécessaires car les fichiers Zip fonctionnent avec des tableaux d'octets, et non avec des chaînes. – OrangeWombat

+0

Mais ... dans l'exemple ci-dessus, comment StringBuilder contient-il autre chose que "Test String"? Je suis un peu confus par cela aussi. Si vous écrivez 'sb.toString(). GetBytes()' dans le fichier ZIP, je m'attendrais à ce que vous vouliez qu'il contienne les octets du fichier que vous compressez? Ou est-ce que je manque quelque chose? – RobA

26

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 l'opération 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(); 
3
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"); 
    } 
}  

} 
2

Zip4j utilise le code complètement java sans support de code natif, et c'est ce qui en fait un meilleur adapté pour moi. Zip4j offre des fonctionnalités suivantes:

  • Créez, ajoutez, extrait, mise à jour, Supprimer des fichiers à partir d'un fichier Zip
  • mot de passe en lecture/écriture protégée des fichiers Zip
  • Prise en charge AES 128/256 cryptage
  • Prise en charge du chiffrement Zip standard
  • Prise en charge du format Zip64
  • Prend en charge la méthode de compression Store (sans compression) et de dégonflage
  • Créer ou extraire des fichiers de Split fichiers Zip (Ex: Z01, Z02, ... zip)
  • Prend en charge les noms de fichiers Unicode
  • Progress Moniteur

CreatePasswordProtectedZipExample.java

import java.io.File; 
import java.util.ArrayList; 

import net.lingala.zip4j.core.ZipFile; 
import net.lingala.zip4j.exception.ZipException; 
import net.lingala.zip4j.model.ZipParameters; 
import net.lingala.zip4j.util.Zip4jConstants; 

public class CreatePasswordProtectedZipExample 
{ 
    public static void main(String[] args) 
    { 
     try { 
      //This is name and path of zip file to be created 
      ZipFile zipFile = new ZipFile("C:/temp/test.zip"); 

      //Add files to be archived into zip file 
      ArrayList<File> filesToAdd = new ArrayList<File>(); 
      filesToAdd.add(new File("C:/temp/test1.txt")); 
      filesToAdd.add(new File("C:/temp/test2.txt")); 

      //Initiate Zip Parameters which define various properties 
      ZipParameters parameters = new ZipParameters(); 
      parameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE); // set compression method to deflate compression 

      //DEFLATE_LEVEL_FASTEST  - Lowest compression level but higher speed of compression 
      //DEFLATE_LEVEL_FAST  - Low compression level but higher speed of compression 
      //DEFLATE_LEVEL_NORMAL - Optimal balance between compression level/speed 
      //DEFLATE_LEVEL_MAXIMUM  - High compression level with a compromise of speed 
      //DEFLATE_LEVEL_ULTRA  - Highest compression level but low speed 
      parameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL); 

      //Set the encryption flag to true 
      parameters.setEncryptFiles(true); 

      //Set the encryption method to AES Zip Encryption 
      parameters.setEncryptionMethod(Zip4jConstants.ENC_METHOD_AES); 

      //AES_STRENGTH_128 - For both encryption and decryption 
      //AES_STRENGTH_192 - For decryption only 
      //AES_STRENGTH_256 - For both encryption and decryption 
      //Key strength 192 cannot be used for encryption. But if a zip file already has a 
      //file encrypted with key strength of 192, then Zip4j can decrypt this file 
      parameters.setAesKeyStrength(Zip4jConstants.AES_STRENGTH_256); 

      //Set password 
      parameters.setPassword("howtodoinjava"); 

      //Now add files to the zip file 
      zipFile.addFiles(filesToAdd, parameters); 
     } 
     catch (ZipException e) 
     { 
      e.printStackTrace(); 
     } 
    } 
} 
58

Java 7 a ZipFileSystem intégré, qui peut être utilisé pour créer, écrire et lire des fichiers à partir du fichier zip.

Java Doc: ZipFileSystem Provider

Map<String, String> env = new HashMap<>(); 
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); 
} 
+11

Cela mérite plus de votes positifs. – xlm

+0

C'est la bonne réponse pour> = Java 7 –

+0

Y at-il un moyen de faire ce travail si l'extension n'est pas '.zip'? J'ai besoin d'écrire un fichier '.foo', qui est formaté exactement comme un fichier zip, mais avec une extension différente. Je sais que je pourrais faire un fichier '.zip' et le renommer, mais le créer avec le bon nom serait plus simple. –

0

Si vous voulez décompresser sans logiciel mieux utiliser ce code. Autre code avec des fichiers pdf envoie erreur sur décompressez manuellement

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(); 
    } 
1

contrôleur de démarrage de printemps, zip les fichiers dans un répertoire, et peut être téléchargé.

@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(); 
} 
0

Depuis, il m'a fallu un certain temps pour comprendre, je pensais que ce serait utile de poster 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);    
    } 
} 
5

Voici un exemple de code pour compresser un entier Répertoire (y compris les sous-dossiers et sous-répertoires), il utilise la fonction 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) { 
     Path sourceDir = Paths.get(dirPath); 
     String zipFileName = dirPath.concat(".zip"); 
     try { 
      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

Questions connexes