So erstellen Sie eine Zip-Datei in Java

149

Ich habe eine dynamische Textdatei, die Inhalte aus einer Datenbank gemäß der Benutzerabfrage auswählt. Ich muss diesen Inhalt in eine Textdatei schreiben und in einen Ordner in einem Servlet komprimieren. Wie soll ich das machen?

Ashish Agarwal
quelle

Antworten:

231

Schauen Sie sich dieses Beispiel an:

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

Dadurch wird im Stammverzeichnis von D:named eine Zip- test.zipDatei erstellt, die eine einzelne aufgerufene Datei enthält mytext.txt. Natürlich können Sie weitere Zip-Einträge hinzufügen und auch ein Unterverzeichnis wie das folgende angeben:

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

Weitere Informationen zur Komprimierung mit Java finden Sie hier .

Chris
quelle
1
Warum sind die beiden Zeilen byte[] data = sb.toString().getBytes(); out.write(data, 0, data.length);in diesem Codebeispiel enthalten? Was ist ihr Zweck?
Kaadzia
@kdzia, die erste Zeile konvertiert den StringBuilder-Wert in ein Byte-Array, und die zweite Zeile nimmt dieses Byte-Array und schreibt es in den ZipEntry in der Datei "test.zip". Diese Zeilen sind erforderlich, da Zip-Dateien mit Byte-Arrays und nicht mit Zeichenfolgen arbeiten.
OrangeWombat
3
Aber ... wie enthält der StringBuilder im obigen Beispiel etwas anderes als "Test String"? Das verwirrt mich auch ein wenig. Wenn Sie das sb.toString().getBytes()in die ZIP-Datei schreiben , würde ich erwarten, dass es die Bytes der Datei enthält, die Sie komprimieren? Oder fehlt mir etwas?
RobA
3
@RobA dir fehlt nichts. Der StringBuilder soll in der Tat den Text enthalten, den das OP aus seiner Datenbank erhalten hat. OP müsste einfach "Test String" (einschließlich der Anführungszeichen) für etwas wie getTextFromDatabase ()
Blueriver
Vielen Dank, @Blueriver
RobA
143

In Java 7 ist ZipFileSystem integriert, mit dem Dateien aus Zip-Dateien erstellt, geschrieben und gelesen werden können.

Java Doc: ZipFileSystem Provider

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
quelle
1
Gibt es eine Möglichkeit, diese Funktion auszuführen, wenn die Erweiterung nicht vorhanden ist .zip? Ich muss eine .fooDatei schreiben , die genau wie eine Zip-Datei formatiert ist, aber eine andere Erweiterung hat. Ich weiß, dass ich eine .zipDatei erstellen und umbenennen könnte, aber es wäre einfacher, sie nur mit dem richtigen Namen zu erstellen.
Troy Daniels
2
@TroyDaniels Das obige Beispiel funktioniert auch mit einer anderen Erweiterung, da das jar:file:Präfix zum Erstellen des URI verwendet wird.
Sivabalan
10
Das einzige Problem, das hier auftreten kann, ist, dass es nicht funktioniert, wenn Sie Verzeichnisse haben. Wenn Sie beispielsweise "/dir/SomeTextFile.txt" in der pathInZipfileVariablen haben, müssen Sie das 'dir' im .zip-Archiv erstellen. Fügen Sie dazu einfach die nächste Zeile hinzu: Files.createDirectories(pathInZipfile.getParent())bevor Sie die Files.copyMethode aufrufen .
D. Naumovich
Wie stelle ich die Komprimierungsstufe ein?
cdalxndr
34

Zum Schreiben einer ZIP-Datei verwenden Sie einen ZipOutputStream. Für jeden Eintrag, den Sie in die ZIP-Datei einfügen möchten, erstellen Sie ein ZipEntry-Objekt. Sie übergeben den Dateinamen an den ZipEntry-Konstruktor. Es legt die anderen Parameter wie Dateidatum und Dekomprimierungsmethode fest. Sie können diese Einstellungen überschreiben, wenn Sie möchten. Anschließend rufen Sie die putNextEntry-Methode des ZipOutputStream auf, um mit dem Schreiben einer neuen Datei zu beginnen. Senden Sie die Dateidaten an den ZIP-Stream. Wenn Sie fertig sind, rufen Sie closeEntry auf. Wiederholen Sie diesen Vorgang für alle Dateien, die Sie speichern möchten. Hier ist ein Code-Skelett:

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
quelle
22

Hier ist ein Beispielcode zum Komprimieren eines gesamten Verzeichnisses (einschließlich Unterdateien und Unterverzeichnissen). Er verwendet die Walk-Dateibaumfunktion von 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();
        }
    }
}

Um dies zu nutzen, rufen Sie einfach an

ZipCompress.compress("target/directoryToCompress");

und Sie erhalten eine Zip-Datei directoryToCompress.zip

Owen Cao
quelle
4

Spring Boot Controller, komprimieren Sie die Dateien in einem Verzeichnis und können heruntergeladen werden.

@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
quelle
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");
    }
 }    

}
Dhiral Pandya
quelle
2

So erstellen Sie eine Zip-Datei aus einer Quelldatei:

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);
}
Live-Liebe
quelle
1

Einzelne Datei:

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

Mehrere Dateien:

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
quelle
1

Sie müssen hauptsächlich zwei Funktionen erstellen. Das erste ist writeToZipFile () und das zweite ist createZipfileForOutPut .... und dann das createZipfileForOutPut ('Dateiname von .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
quelle
0

Wenn Sie ohne Software dekomprimieren möchten, verwenden Sie diesen Code besser. Anderer Code mit PDF-Dateien sendet beim manuellen Dekomprimieren einen Fehler

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
quelle
0

Da ich eine Weile gebraucht habe, um es herauszufinden, hielt ich es für hilfreich, meine Lösung mit Java 7+ ZipFileSystem zu veröffentlichen

 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.
quelle
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());
        }
    }
}
鄒成立
quelle
0

Gegeben exportPathund queryResultsals String-Variablen erstellt der folgende Block eine results.zipDatei unter exportPathund schreibt den Inhalt queryResultsin eine results.txtDatei innerhalb der Zip-Datei.

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
quelle
0

Mit Jeka https://jeka.dev JkPathTree ist das ganz einfach.

Path wholeDirToZip = Paths.get("dir/to/zip");
Path zipFile = Paths.get("file.zip");
JkPathTree.of(wholeDirToZip).zipTo(zipFile);
Jerome Angibaud
quelle
0

Es ist eine weitere Option , indem Sie zip4jbei https://github.com/srikanth-lingala/zip4j

Erstellen einer Zip-Datei mit einer einzelnen Datei / Hinzufügen einer einzelnen Datei zu einer vorhandenen Zip

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

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

Erstellen einer Zip-Datei mit mehreren Dateien / Hinzufügen mehrerer Dateien zu einer vorhandenen Zip

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

Erstellen einer Zip-Datei durch Hinzufügen eines Ordners / Hinzufügen eines Ordners zu einer vorhandenen Zip-Datei

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

Erstellen einer Zip-Datei aus Stream / Hinzufügen eines Streams zu einer vorhandenen Zip new ZipFile("filename.zip").addStream(inputStream, new ZipParameters());

sendon1982
quelle