วิธีสร้างไฟล์ zip ใน Java


149

ฉันมีไฟล์ข้อความแบบไดนามิกที่เลือกเนื้อหาจากฐานข้อมูลตามแบบสอบถามของผู้ใช้ ฉันต้องเขียนเนื้อหานี้ลงในไฟล์ข้อความและซิปในโฟลเดอร์ในเซิร์ฟเล็ต ฉันจะทำสิ่งนี้ได้อย่างไร

คำตอบ:


231

ดูตัวอย่างนี้:

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

นี้จะสร้างซิปในรากของการD:ตั้งชื่อซึ่งจะมีไฟล์เดียวที่เรียกว่าtest.zip mytext.txtแน่นอนคุณสามารถเพิ่มรายการ zip เพิ่มเติมและระบุไดเรกทอรีย่อยเช่นนี้:

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

คุณสามารถค้นหาข้อมูลเพิ่มเติมเกี่ยวกับการบีบอัดกับ Java ที่นี่


1
เหตุใดจึงมีสองบรรทัด: byte[] data = sb.toString().getBytes(); out.write(data, 0, data.length);รวมอยู่ในตัวอย่างโค้ดนี้ วัตถุประสงค์ของพวกเขาคืออะไร?
Kaadzia

@kdzia บรรทัดแรกแปลงค่า StringBuilder เป็นอาร์เรย์ไบต์และบรรทัดที่สองใช้อาร์เรย์ไบต์นั้นและเขียนลงใน ZipEntry ภายในไฟล์ "test.zip" บรรทัดเหล่านี้มีความจำเป็นเนื่องจากไฟล์ซิปทำงานกับอาร์เรย์ไบต์ไม่ใช่สตริง
OrangeWombat

3
แต่ ... ในตัวอย่างข้างต้น StringBuilder มีอะไรในนั้นนอกเหนือจาก "Test String" ได้อย่างไร ฉันก็สับสนเล็กน้อยเช่นกัน หากคุณกำลังเขียนsb.toString().getBytes()ไปยังไฟล์ ZIP ฉันคาดว่าคุณต้องการให้มีจำนวนไบต์ของไฟล์ที่คุณซิป หรือว่าฉันขาดอะไรไป?
RobA

3
@RobA คุณจะไม่พลาดอะไรเลย StringBuilder นั้นหมายถึงการบรรจุข้อความที่ OP ได้รับจากฐานข้อมูลของเขา OP ก็จะต้องแทนที่ "การทดสอบสตริง" (รวมถึงคำพูด) สำหรับบางสิ่งบางอย่างเช่น getTextFromDatabase ()
Blueriver

ขอบคุณ @Blueriver
RobA

143

Java 7 มี ZipFileSystem ในตัวซึ่งสามารถใช้เพื่อสร้างเขียนและอ่านไฟล์จากไฟล์ zip

Java Doc: ผู้ให้บริการ 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
มีวิธีทำให้งานนี้ถ้าส่วนขยายไม่ได้.zipหรือไม่ ฉันต้องเขียน.fooไฟล์ซึ่งมีรูปแบบเหมือนกับไฟล์ zip แต่มีนามสกุลต่างกัน ฉันรู้ว่าฉันสามารถสร้าง.zipไฟล์และเปลี่ยนชื่อไฟล์ได้ แต่เพียงสร้างด้วยชื่อที่ถูกต้องก็จะง่ายขึ้น
ทรอยแดเนียลส์

2
@TroyDaniels ตัวอย่างข้างต้นทำงานร่วมกับส่วนขยายที่แตกต่างกันเช่นกันเนื่องจากใช้jar:file:คำนำหน้าเพื่อสร้าง URI
ศิวาบาลัน

10
ปัญหาเดียวที่สามารถปรากฏที่นี่คือมันจะไม่ทำงานในกรณีที่คุณมีไดเรกทอรี ตัวอย่างเช่นหากคุณมี "/dir/SomeTextFile.txt" ในpathInZipfileตัวแปรคุณจะต้องสร้าง 'dir' ภายในไฟล์. zip สำหรับสิ่งนี้เพียงเพิ่มบรรทัดถัดไป: Files.createDirectories(pathInZipfile.getParent())ก่อนที่จะเรียกใช้Files.copyเมธอด
D. Naumovich

วิธีการตั้งค่าระดับการบีบอัด?
cdalxndr

34

ในการเขียนไฟล์ ZIP คุณใช้ ZipOutputStream สำหรับแต่ละรายการที่คุณต้องการวางลงในไฟล์ ZIP คุณสร้างวัตถุ ZipEntry คุณส่งชื่อไฟล์ไปยังตัวสร้าง ZipEntry มันตั้งค่าพารามิเตอร์อื่น ๆ เช่นวันที่ไฟล์และวิธีการบีบอัด คุณสามารถแทนที่การตั้งค่าเหล่านี้ได้หากต้องการ จากนั้นคุณเรียกใช้เมธอด putNextEntry ของ ZipOutputStream เพื่อเริ่มเขียนไฟล์ใหม่ ส่งข้อมูลไฟล์ไปยังสตรีม ZIP เมื่อเสร็จแล้วให้โทร closeEntry ทำซ้ำสำหรับไฟล์ทั้งหมดที่คุณต้องการจัดเก็บ นี่คือโครงกระดูกรหัส:

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

นี่คือตัวอย่างรหัสในการบีบอัดทั้งไดเรกทอรี (รวมถึงไฟล์ย่อยและไดเรกทอรีย่อย) โดยใช้คุณลักษณะแผนผังไฟล์ของ 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();
        }
    }
}

หากต้องการใช้สิ่งนี้เพียงโทร

ZipCompress.compress("target/directoryToCompress");

และคุณจะได้รับไฟล์ zip ไปยังไดเรกทอรีคอมเพรส.zip


4

สปริงตัวควบคุมการบู๊ตซิปไฟล์ในไดเรกทอรีและสามารถดาวน์โหลดได้

@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

นี่คือวิธีที่คุณสร้างไฟล์ zip จากไฟล์ต้นฉบับ:

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

ไฟล์เดียว:

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

หลายไฟล์:

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

คุณมีหลักในการสร้างสองฟังก์ชั่น อันดับแรกคือ writeToZipFile () และอันดับที่สองคือ createZipfileForOutPut .... แล้วเรียกใช้ createZipfileForOutPut ('ชื่อไฟล์ของ. 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

หากคุณต้องการคลายการบีบอัดโดยไม่มีซอฟต์แวร์ให้ใช้รหัสนี้ดีกว่า รหัสอื่นที่มีไฟล์ pdf จะส่งข้อผิดพลาดในการขยายขนาดด้วยตนเอง

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

เนื่องจากฉันใช้เวลาซักพักนึงฉันคิดว่ามันจะมีประโยชน์ในการโพสต์โซลูชันของฉันโดยใช้ 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

ให้exportPathและqueryResultsเป็นตัวแปรสตริงบล็อกต่อไปนี้สร้างresults.zipไฟล์ภายใต้exportPathและเขียนเนื้อหาของqueryResultsไปยังresults.txtไฟล์ภายในซิป

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

มีตัวเลือกอื่นโดยใช้zip4jที่https://github.com/srikanth-lingala/zip4j

การสร้างไฟล์ zip ด้วยไฟล์เดียวในนั้น / การเพิ่มไฟล์เดียวไปยัง zip ที่มีอยู่

new ZipFile("filename.zip").addFile("filename.ext"); หรือ

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

การสร้างไฟล์ zip ด้วยหลายไฟล์ / การเพิ่มหลายไฟล์ไปยัง zip ที่มีอยู่

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

การสร้างไฟล์ zip โดยการเพิ่มโฟลเดอร์ลงใน / การเพิ่มโฟลเดอร์ไปยังไฟล์ zip ที่มีอยู่

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

การสร้างไฟล์ zip จากสตรีม / การเพิ่มสตรีมไปยัง zip ที่มีอยู่ new ZipFile("filename.zip").addStream(inputStream, new ZipParameters());

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.