2013-04-12 41 views
43

Giả sử tôi có cấu trúc thư mục sau.cách tự nén một thư mục bằng cách sử dụng java

D:\reports\january\ 

Bên trong tháng một có giả sử hai tệp excel nói A.xls và B.xls. Có rất nhiều nơi mà nó đã được viết về cách nén các tệp bằng cách sử dụng java.util.zip. Nhưng tôi muốn nén chính thư mục january bên trong thư mục báo cáo để cả hai tháng mộtjanuary.zip sẽ có mặt trong các báo cáo. (Điều đó có nghĩa là khi tôi giải nén tệp january.zip tôi sẽ nhận được thư mục tháng một).

Bất kỳ ai cũng có thể cung cấp cho tôi mã để thực hiện việc này bằng cách sử dụng java.util.zip. Vui lòng cho tôi biết liệu điều này có thể dễ dàng hơn bằng cách sử dụng các thư viện khác hay không.

Cảm ơn rất nhiều ...

+4

Tại sao người kiểm duyệt không đóng loại câu hỏi này, trực tiếp chống lại các quy tắc từ trang đầu tiên "Không hỏi ... Các câu hỏi bạn chưa tìm được câu trả lời (hiển thị công việc của bạn!) ". – CheatEx

Trả lời

37

Nó có thể có thể dễ dàng được giải quyết theo gói java.util.Zip không cần thêm bất kỳ Jar tệp

Chỉ cần sao chép đoạn mã sau và run it với bạn IDE

//Import all needed packages 
package general; 
import java.io.File; 
import java.io.FileInputStream; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.util.ArrayList; 
import java.util.List; 
import java.util.zip.ZipEntry; 
import java.util.zip.ZipOutputStream; 

public class ZipUtils { 

    private List <String> fileList; 
    private static final String OUTPUT_ZIP_FILE = "Folder.zip"; 
    private static final String SOURCE_FOLDER = "D:\\Reports"; // SourceFolder path 

    public ZipUtils() { 
     fileList = new ArrayList <String>(); 
    } 

    public static void main(String[] args) { 
     ZipUtils appZip = new ZipUtils(); 
     appZip.generateFileList(new File(SOURCE_FOLDER)); 
     appZip.zipIt(OUTPUT_ZIP_FILE); 
    } 

    public void zipIt(String zipFile) { 
     byte[] buffer = new byte[1024]; 
     String source = new File(SOURCE_FOLDER).getName(); 
     FileOutputStream fos = null; 
     ZipOutputStream zos = null; 
     try { 
      fos = new FileOutputStream(zipFile); 
      zos = new ZipOutputStream(fos); 

      System.out.println("Output to Zip : " + zipFile); 
      FileInputStream in = null; 

      for (String file: this.fileList) { 
       System.out.println("File Added : " + file); 
       ZipEntry ze = new ZipEntry(source + File.separator + file); 
       zos.putNextEntry(ze); 
       try { 
        in = new FileInputStream(SOURCE_FOLDER + File.separator + file); 
        int len; 
        while ((len = in .read(buffer)) > 0) { 
         zos.write(buffer, 0, len); 
        } 
       } finally { 
        in.close(); 
       } 
      } 

      zos.closeEntry(); 
      System.out.println("Folder successfully compressed"); 

     } catch (IOException ex) { 
      ex.printStackTrace(); 
     } finally { 
      try { 
       zos.close(); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
     } 
    } 

    public void generateFileList(File node) { 
     // add file only 
     if (node.isFile()) { 
      fileList.add(generateZipEntry(node.toString())); 
     } 

     if (node.isDirectory()) { 
      String[] subNote = node.list(); 
      for (String filename: subNote) { 
       generateFileList(new File(node, filename)); 
      } 
     } 
    } 

    private String generateZipEntry(String file) { 
     return file.substring(SOURCE_FOLDER.length() + 1, file.length()); 
    } 
} 

Tham khảo mkyong ..Tôi đã thay đổi mã cho các yêu cầu của câu hỏi hiện tại

0

Bạn sẽ phải thêm mỗi và mọi tệp trong thư mục và đệ quy đi qua thư mục con. Có rất nhiều ví dụ nếu bạn google nó.

3

Tôi sẽ sử dụng Apache Ant, trong đó có API để gọi nhiệm vụ từ mã Java thay vì từ tệp xây dựng XML.

Project p = new Project(); 
p.init(); 
Zip zip = new Zip(); 
zip.setProject(p); 
zip.setDestFile(zipFile); // a java.io.File for the zip you want to create 
zip.setBasedir(new File("D:\\reports")); 
zip.setIncludes("january/**"); 
zip.perform(); 

Ở đây tôi đang nói nó để bắt đầu từ thư mục cơ sở D:\reports và zip lên các january thư mục và tất cả mọi thứ bên trong nó. Đường dẫn trong tệp zip kết quả sẽ giống với đường dẫn ban đầu tương ứng với D:\reports, vì vậy chúng sẽ bao gồm tiền tố january.

71

Bạn đã thử thư viện Zeroturnaround Zip chưa? Nó thực sự gọn gàng! Zip một thư mục chỉ là một liner:

ZipUtil.pack(new File("D:\\reports\\january\\"), new File("D:\\reports\\january.zip")); 

(nhờ Oleg Šelajev ví dụ)

+0

nếu tôi cần thêm một tệp nữa, ở cấp thư mục cách thực hiện bằng cách sử dụng thư viện này – user2478236

5

Tôi thường sử dụng một lớp helper Tôi đã từng viết cho nhiệm vụ này:

import java.util.zip.*; 
import java.io.*; 

public class ZipExample { 
    public static void main(String[] args){ 
     ZipHelper zippy = new ZipHelper(); 
     try { 
      zippy.zipDir("folderName","test.zip"); 
     } catch(IOException e2) { 
      System.err.println(e2); 
     } 
    } 
} 

class ZipHelper 
{ 
    public void zipDir(String dirName, String nameZipFile) throws IOException { 
     ZipOutputStream zip = null; 
     FileOutputStream fW = null; 
     fW = new FileOutputStream(nameZipFile); 
     zip = new ZipOutputStream(fW); 
     addFolderToZip("", dirName, zip); 
     zip.close(); 
     fW.close(); 
    } 

    private void addFolderToZip(String path, String srcFolder, ZipOutputStream zip) throws IOException { 
     File folder = new File(srcFolder); 
     if (folder.list().length == 0) { 
      addFileToZip(path , srcFolder, zip, true); 
     } 
     else { 
      for (String fileName : folder.list()) { 
       if (path.equals("")) { 
        addFileToZip(folder.getName(), srcFolder + "/" + fileName, zip, false); 
       } 
       else { 
        addFileToZip(path + "/" + folder.getName(), srcFolder + "/" + fileName, zip, false); 
       } 
      } 
     } 
    } 

    private void addFileToZip(String path, String srcFile, ZipOutputStream zip, boolean flag) throws IOException { 
     File folder = new File(srcFile); 
     if (flag) { 
      zip.putNextEntry(new ZipEntry(path + "/" +folder.getName() + "/")); 
     } 
     else { 
      if (folder.isDirectory()) { 
       addFolderToZip(path, srcFile, zip); 
      } 
      else { 
       byte[] buf = new byte[1024]; 
       int len; 
       FileInputStream in = new FileInputStream(srcFile); 
       zip.putNextEntry(new ZipEntry(path + "/" + folder.getName())); 
       while ((len = in.read(buf)) > 0) { 
        zip.write(buf, 0, len); 
       } 
      } 
     } 
    } 
} 
+3

Bạn nên đóng luồng đầu vào của mình cho FileInputStream khi bạn hoàn tất. –

7

Java 7+, commons.io

public final class ZipUtils { 

    public static void zipFolder(final File folder, final File zipFile) throws IOException { 
     zipFolder(folder, new FileOutputStream(zipFile)); 
    } 

    public static void zipFolder(final File folder, final OutputStream outputStream) throws IOException { 
     try (ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream)) { 
      processFolder(folder, zipOutputStream, folder.getPath().length() + 1); 
     } 
    } 

    private static void processFolder(final File folder, final ZipOutputStream zipOutputStream, final int prefixLength) 
      throws IOException { 
     for (final File file : folder.listFiles()) { 
      if (file.isFile()) { 
       final ZipEntry zipEntry = new ZipEntry(file.getPath().substring(prefixLength)); 
       zipOutputStream.putNextEntry(zipEntry); 
       try (FileInputStream inputStream = new FileInputStream(file)) { 
        IOUtils.copy(inputStream, zipOutputStream); 
       } 
       zipOutputStream.closeEntry(); 
      } else if (file.isDirectory()) { 
       processFolder(file, zipOutputStream, prefixLength); 
      } 
     } 
    } 
} 
+0

Nếu bạn muốn loại bỏ sự phụ thuộc vào commons.io, phương thức 'IOUtils.copy' là khá nhiều: ' byte [] buffer = new byte [1024 * 4]; int read = 0; while ((read = input.read (buffer))! = -1) { output.write (bộ đệm, 0, đọc); } ' –

1

Hãy thử điều này:

import java.io.File; 

import java.io.FileInputStream; 

import java.io.FileOutputStream; 

import java.util.zip.ZipEntry; 

import java.util.zip.ZipOutputStream; 


    public class Zip { 

public static void main(String[] a) throws Exception { 

    zipFolder("D:\\reports\\january", "D:\\reports\\january.zip"); 

    } 

    static public void zipFolder(String srcFolder, String destZipFile) throws Exception { 
    ZipOutputStream zip = null; 
    FileOutputStream fileWriter = null; 
    fileWriter = new FileOutputStream(destZipFile); 
    zip = new ZipOutputStream(fileWriter); 
    addFolderToZip("", srcFolder, zip); 
    zip.flush(); 
    zip.close(); 
    } 
    static private void addFileToZip(String path, String srcFile, ZipOutputStream zip) 
     throws Exception { 
    File folder = new File(srcFile); 
    if (folder.isDirectory()) { 
     addFolderToZip(path, srcFile, zip); 
    } else { 
     byte[] buf = new byte[1024]; 
     int len; 
     FileInputStream in = new FileInputStream(srcFile); 
     zip.putNextEntry(new ZipEntry(path + "/" + folder.getName())); 
     while ((len = in.read(buf)) > 0) { 
     zip.write(buf, 0, len); 
     } 
    } 
    } 

    static private void addFolderToZip(String path, String srcFolder, ZipOutputStream zip) 
     throws Exception { 
    File folder = new File(srcFolder); 

    for (String fileName : folder.list()) { 
     if (path.equals("")) { 
     addFileToZip(folder.getName(), srcFolder + "/" + fileName, zip); 
     } else { 
     addFileToZip(path + "/" + folder.getName(), srcFolder + "/" + fileName, zip); 
     } 
    } 
    } 



    } 
33

Đây là Java 8 + Ví dụ:

public static void pack(String sourceDirPath, String zipFilePath) throws IOException { 
    Path p = Files.createFile(Paths.get(zipFilePath)); 
    try (ZipOutputStream zs = new ZipOutputStream(Files.newOutputStream(p))) { 
     Path pp = Paths.get(sourceDirPath); 
     Files.walk(pp) 
      .filter(path -> !Files.isDirectory(path)) 
      .forEach(path -> { 
       ZipEntry zipEntry = new ZipEntry(pp.relativize(path).toString()); 
       try { 
        zs.putNextEntry(zipEntry); 
        Files.copy(path, zs); 
        zs.closeEntry(); 
      } catch (IOException e) { 
       System.err.println(e); 
      } 
      }); 
    } 
} 
+1

Cải tiến nhỏ: Đặt ZipOutpuStream trong thử (...) {}; Đối với sp, tôi đã thêm .replace ("\\", "/"); thay thế sp + "/" + path ... bằng sp + path ... – Anthony

+3

Lấy đường dẫn tương đối cho ZipEntry có thể được đơn giản hóa thành 'new ZipEntry (pp.relativize (path) .toString())' – simon04

+0

Cảm ơn! Mã này hoạt động hoàn hảo cho nhu cầu của tôi. – Keshav

28

Dưới đây là một khá ngắn gọn Java 7+ giải pháp mà dựa hoàn toàn vào lớp vani JDK, không thư viện của bên thứ ba bắt buộc:

public static void pack(final Path folder, final Path zipFilePath) throws IOException { 
    try (
      FileOutputStream fos = new FileOutputStream(zipFilePath.toFile()); 
      ZipOutputStream zos = new ZipOutputStream(fos) 
    ) { 
     Files.walkFileTree(folder, new SimpleFileVisitor<Path>() { 
      public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { 
       zos.putNextEntry(new ZipEntry(folder.relativize(file).toString())); 
       Files.copy(file, zos); 
       zos.closeEntry(); 
       return FileVisitResult.CONTINUE; 
      } 

      public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { 
       zos.putNextEntry(new ZipEntry(folder.relativize(dir).toString() + "/")); 
       zos.closeEntry(); 
       return FileVisitResult.CONTINUE; 
      } 
     }); 
    } 
} 

Nó sao chép tất cả các tệp trong folder, bao gồm các thư mục trống và tạo lưu trữ zip tại zipFilePath.

+0

phương pháp này có một số vấn đề nếu bạn tạo zip trên cửa sổ và sử dụng zip này trên linux! – aeroxr1

+2

Bạn có thể cụ thể hơn không? Bạn đang gặp phải vấn đề gì? – jjst

+0

Phương thức Fonder.relativize (dir) sử dụng dấu phân cách hệ thống và trong trường hợp Windows là \ và đây là vấn đề khi bạn tạo một mã zip trên hệ thống cửa sổ và sử dụng nó trên hệ thống Unix. Bạn sẽ thấy các tệp bên ngoài các thư mục của nó. Có vấn đề khác, trên Linux previsitDirectory cũng truy cập vào thư mục "" và theo cách này nếu bạn nén Thư mục trong một zip có tên "test.zip" trên hệ thống Linux bên trong zip đó bạn sẽ tìm thấy tất cả các tệp cộng với một thư mục trống có tên " kiểm tra " – aeroxr1

0

Java 6 +

import java.io.*; 
import java.util.zip.ZipEntry; 
import java.util.zip.ZipOutputStream; 

public class Zip { 

    private static final FileFilter FOLDER_FILTER = new FileFilter() { 
     @Override 
     public boolean accept(File pathname) { 
      return pathname.isDirectory(); 
     } 
    }; 

    private static final FileFilter FILE_FILTER = new FileFilter() { 
     @Override 
     public boolean accept(File pathname) { 
      return pathname.isFile(); 
     } 
    }; 


    private static void compress(File file, ZipOutputStream outputStream, String path) throws IOException { 

     if (file.isDirectory()) { 
      File[] subFiles = file.listFiles(FILE_FILTER); 
      if (subFiles != null) { 
       for (File subFile : subFiles) { 
        compress(subFile, outputStream, new File(path, subFile.getName()).getAbsolutePath()); 
       } 
      } 
      File[] subDirs = file.listFiles(FOLDER_FILTER); 
      if (subDirs != null) { 
       for (File subDir : subDirs) { 
        compress(subDir, outputStream, new File(path, subDir.getName()).getAbsolutePath()); 
       } 
      } 
     } else if (file.exists()) { 
      outputStream.putNextEntry(new ZipEntry(path)); 
      FileInputStream inputStream = new FileInputStream(file); 
      byte[] buffer = new byte[1024]; 
      int len; 
      while ((len = inputStream.read(buffer)) >= 0) { 
       outputStream.write(buffer, 0, len); 
      } 
      outputStream.closeEntry(); 
     } 
    } 

    public static void compress(String dirPath, String zipFilePath) throws IOException { 
     File file = new File(dirPath); 
     final ZipOutputStream outputStream = new ZipOutputStream(new FileOutputStream(zipFilePath)); 
     compress(file, outputStream, "/"); 
     outputStream.close(); 
    } 

} 
0

tôi tìm thấy giải pháp này làm việc hoàn toàn tốt đẹp cho tôi. Không yêu cầu bất kỳ bên thứ ba nào apis

'thử nghiệm' thực sự là một thư mục sẽ chứa nhiều tệp bên trong.

String folderPath= "C:\Users\Desktop\test"; 
String zipPath = "C:\Users\Desktop\test1.zip"; 

private boolean zipDirectory(String folderPath, String zipPath) throws IOException{ 

     byte[] buffer = new byte[1024]; 
     FileInputStream fis = null; 
     ZipOutputStream zos = null; 

     try{ 
      zos = new ZipOutputStream(new FileOutputStream(zipPath)); 
      updateSourceFolder(new File(folderPath)); 

      if (sourceFolder == null) { 
       zos.close(); 
       return false; 
      } 
      generateFileAndFolderList(new File(folderPath)); 

      for (String unzippedFile: fileList) { 
       System.out.println(sourceFolder + unzippedFile); 

       ZipEntry entry = new ZipEntry(unzippedFile); 
       zos.putNextEntry(entry); 

       if ((unzippedFile.substring(unzippedFile.length()-1)).equals(File.separator)) 
        continue; 
       try{ 
        fis = new FileInputStream(sourceFolder + unzippedFile); 
        int len=0; 
        while ((len = fis.read(buffer))>0) { 
         zos.write(buffer,0,len); 
        } 
       } catch(IOException e) { 
        return false; 
       } finally { 
        if (fis != null) 
         fis.close(); 
       } 
      } 
      zos.closeEntry(); 
     } catch(IOException e) { 
      return false; 
     } finally { 
      zos.close(); 
      fileList = null; 
      sourceFolder = null; 
     } 
     return true; 
    } 

    private void generateFileAndFolderList(File node) { 
     if (node.isFile()) { 
      fileList.add(generateZipEntry(node.getAbsoluteFile().toString())); 
     } 
     if (node.isDirectory()) { 
      String dir = node.getAbsoluteFile().toString(); 
      fileList.add(dir.substring(sourceFolder.length(), dir.length()) + File.separator); 

      String[] subNode = node.list(); 
      for (String fileOrFolderName : subNode) { 
       generateFileAndFolderList(new File(node, fileOrFolderName)); 
      } 
     } 
    } 

    private void updateSourceFolder(File node) { 
     if (node.isFile() || node.isDirectory()) { 
      String sf = node.getAbsoluteFile().toString(); 
      sourceFolder = sf.substring(0, (sf.lastIndexOf("/") > 0 ? sf.lastIndexOf("/") : sf.lastIndexOf("\\"))); 
      sourceFolder += File.separator; 
     } else 
      sourceFolder = null; 
    } 

    private String generateZipEntry(String file) { 
     return file.substring(sourceFolder.length(), file.length()); 
    } 
Các vấn đề liên quan