Cách tạo tệp zip trong Java


149

Tôi có một tệp văn bản động chọn nội dung từ cơ sở dữ liệu theo truy vấn của người dùng. Tôi phải viết nội dung này vào một tệp văn bản và nén nó vào một thư mục trong một servlet. Làm thế nào tôi nên làm điều này?

Câu trả lời:


231

Nhìn vào ví dụ này:

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

Điều này sẽ tạo ra một zip trong thư mục gốc D:có tên test.zipsẽ chứa một tệp duy nhất được gọi mytext.txt. Tất nhiên, bạn có thể thêm nhiều mục zip và cũng chỉ định thư mục con như thế này:

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

Bạn có thể tìm thêm thông tin về nén với Java tại đây .


1
Tại sao hai dòng: byte[] data = sb.toString().getBytes(); out.write(data, 0, data.length);bao gồm trong mẫu mã này? Mục đích của họ là gì?
Kaadzia

@kdzia, dòng đầu tiên chuyển đổi giá trị StringBuilder thành một mảng byte và dòng thứ hai lấy mảng byte đó và ghi nó vào ZipEntry trong tệp "test.zip". Những dòng này là cần thiết vì các tệp Zip hoạt động với mảng byte, không phải chuỗi.
OrangeWombat

3
Nhưng ... trong ví dụ trên, StringBuilder có bất cứ thứ gì trong đó ngoài "Chuỗi thử nghiệm"? Tôi cũng hơi bối rối vì điều này. Nếu bạn đang ghi sb.toString().getBytes()tệp ZIP, tôi muốn bạn muốn nó chứa byte của tệp bạn đang nén? Hay tôi đang thiếu một cái gì đó?
RobA

3
@RobA bạn không thiếu thứ gì. StringBuilder thực sự có nghĩa là chứa văn bản mà OP có được từ cơ sở dữ liệu của anh ấy. OP chỉ đơn giản là phải thay thế "Chuỗi thử nghiệm" (bao gồm cả dấu ngoặc kép) cho một cái gì đó như getTextFromDatabase ()
Blueriver

Cảm ơn, @Blueriver
Roba

143

Java 7 có ZipFileSystem được tích hợp sẵn, có thể được sử dụng để tạo, ghi và đọc tệp từ tệp zip.

Tài liệu Java: Nhà cung cấp 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); 
}

1
Có cách nào để thực hiện công việc này nếu phần mở rộng không .zip? Tôi cần phải viết một .footệp, được định dạng chính xác như tệp zip, nhưng với một phần mở rộng khác. Tôi biết tôi có thể tạo một .ziptập tin và đổi tên nó, nhưng chỉ cần tạo nó với đúng tên sẽ đơn giản hơn.
Troy Daniels

2
@TroyDaniels ví dụ trên cũng hoạt động với phần mở rộng khác nhau, vì nó sử dụng jar:file:tiền tố để tạo URI.
Sivabalan

10
Vấn đề duy nhất có thể xuất hiện ở đây là nó sẽ không hoạt động trong trường hợp bạn có thư mục. Vì vậy, ví dụ, nếu bạn có "/dir/SomeTextFile.txt" trong pathInZipfilebiến, bạn cần tạo 'dir' bên trong kho lưu trữ .zip. Đối với điều này, chỉ cần thêm dòng tiếp theo: Files.createDirectories(pathInZipfile.getParent())trước khi gọi Files.copyphương thức.
D. Naumovich

Làm thế nào để thiết lập mức nén?
cdalxndr

34

Để viết tệp ZIP, bạn sử dụng ZipOutputStream. Đối với mỗi mục bạn muốn đặt vào tệp ZIP, bạn tạo một đối tượng ZipEntry. Bạn chuyển tên tệp cho hàm tạo ZipEntry; nó đặt các tham số khác như ngày tệp và phương thức giải nén. Bạn có thể ghi đè các cài đặt này nếu bạn muốn. Sau đó, bạn gọi phương thức putNextEntry của ZipOutputStream để bắt đầu viết một tệp mới. Gửi dữ liệu tệp đến luồng ZIP. Khi bạn đã hoàn tất, hãy gọi closeEntry. Lặp lại cho tất cả các tệp bạn muốn lưu trữ. Đây là một bộ xương mã:

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

22

Dưới đây là mã ví dụ để nén Toàn bộ thư mục (bao gồm các tệp phụ và thư mục con), nó sử dụng tính năng cây tập tin đi bộ của 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();
        }
    }
}

Để sử dụng, chỉ cần gọi

ZipCompress.compress("target/directoryToCompress");

và bạn sẽ nhận được một thư mục tệp zipToCompress.zip


4

Bộ điều khiển khởi động mùa xuân, nén các tệp trong một thư mục và có thể được tải xuống.

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

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

}

2

Đây là cách bạn tạo tệp zip từ tệp nguồn:

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

1

Tập tin duy nhất:

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

Nhiều tệp:

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

1

Bạn có chủ yếu để tạo hai chức năng. Đầu tiên là writeToZipFile () và thứ hai là createdZipfileForOutPut .... và sau đó gọi hàm createdZipfileForOutPut ('tên tệp của .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();
    }
}

0

Nếu bạn muốn giải nén mà không cần phần mềm, hãy sử dụng mã này. Mã khác với tệp pdf gửi lỗi khi giải nén thủ công

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

0

Vì tôi phải mất một thời gian để tìm ra nó, tôi nghĩ rằng sẽ rất hữu ích khi đăng giải pháp của mình bằng 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);            
    }
 }

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

0

Với exportPathqueryResultsnhư biến String, khối sau tạo một results.ziptập tin dưới exportPathvà ghi nội dung của queryResultsmột results.txttập tin bên trong 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);
}

0

Sử dụng Jeka https://jeka.dev JkPathTree, nó khá đơn giản.

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

0

Có một tùy chọn khác bằng cách sử dụng zip4jtại https://github.com/srikanth-lingala/zip4j

Tạo một tệp zip với một tệp trong đó / Thêm một tệp vào một zip hiện có

new ZipFile("filename.zip").addFile("filename.ext"); Hoặc là

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

Tạo một tệp zip có nhiều tệp / Thêm nhiều tệp vào một zip hiện có

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

Tạo một tệp zip bằng cách thêm một thư mục vào nó / Thêm một thư mục vào một zip hiện có

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

Tạo tệp zip từ luồng / Thêm luồng vào zip hiện có new ZipFile("filename.zip").addStream(inputStream, new ZipParameters());

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.