web-dev-qa-db-ja.com

javaを使用してフォルダ自体を圧縮する方法

次のディレクトリ構造があるとします。

D:\reports\january\

1月の中には、A.xlsとB.xlsという2つのExcelファイルがあるとします。 Java.util.Zipを使用してファイルを圧縮する方法について書かれている場所はたくさんあります。しかし、レポートフォルダー内に1月フォルダー自体を圧縮して、レポート内にjanuaryjanuary.Zipの両方が存在するようにします。 (つまり、january.Zipファイルを解凍すると、1月のフォルダーを取得する必要があります)。

誰でもJava.util.Zipを使用してこれを行うためのコードを提供してください。他のライブラリを使用することでこれがより簡単にできるかどうかを教えてください。

どうもありがとう...

59
mukund

パッケージで簡単に解決できますJava.util.Zip余分なJarファイルは不要

次のコードとrun itIDEと共にコピーするだけです

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

mkyong を参照してください。現在の質問の要件に合わせてコードを変更しました

53
kark

Zeroturnaround Zip ライブラリを試しましたか?本当にすてきです!フォルダーを圧縮するのは1つのライナーです。

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

(例について OlegŠelajev に感謝)

88
Petro Semeniuk

Java 8+の例は次のとおりです。

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

純粋なVanilla JDKクラスのみに依存する、非常に簡潔なJava 7+ソリューションがあります。サードパーティライブラリは必要ありません。

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

空のディレクトリを含むfolder内のすべてのファイルをコピーし、zipFilePathにZipアーカイブを作成します。

33
jjst

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);
            }
        }
    }
}
11
Tony BenBrahim

私は通常、このタスクのために一度書いたヘルパークラスを使用します。

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

強化されたJava 8+の例( Nikita Koksharov's answer )から分岐

public static void pack(String sourceDirPath, String zipFilePath) throws IOException {
    Path p = Files.createFile(Paths.get(zipFilePath));
    Path pp = Paths.get(sourceDirPath);
    try (ZipOutputStream zs = new ZipOutputStream(Files.newOutputStream(p));
        Stream<Path> paths = Files.walk(pp)) {
        paths
          .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);
            }
          });
    }
}

Files.walktry with resourcesブロックでラップされているため、ストリームを閉じることができます。これにより、SonarQubeで識別されるブロッカーの問題が解決されます。これを指摘してくれた@Matt Harrisonに感謝します。

5
Abdul Rauf

Apache Ant を使用します。これには、XMLビルドファイルからではなく、Javaコードからタスクを呼び出すAPIがあります。

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

ここでは、ベースディレクトリD:\reportsから開始し、januaryフォルダーとその中のすべてを圧縮するように指示しています。結果のZipファイルのパスは、D:\reportsに関連する元のパスと同じになるため、januaryプレフィックスが含まれます。

4
Ian Roberts

これを試して:

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



   }
2
Denis

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

}
1
Dillion Wang

Zip4j を使用すると、簡単にこれを行うことができます

ZipFile zipfile = new ZipFile(new File("D:\\reports\\january\\filename.Zip"));
zipfile.addFolder(new File("D:\\reports\\january\\"));

それはあなたのフォルダとその中のすべてをアーカイブします。

.extractAllメソッドを使用して、すべてを取得します。

zipfile.extractAll("D:\\destination_directory");
1
svarog

このソリューションは私にとって完璧に機能することがわかりました。サードパーティのAPIは必要ありません

「テスト」は、実際にはフォルダー内にたくさんのファイルがあります。

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

このメソッドは、フォルダーを圧縮し、すべての子ファイルとフォルダー(空のフォルダーを含む)をZipファイルに追加します。

void zipFolder(Path sourceDir, Path targetFile) throws IOException {
    ZipDirectoryVisitor zipVisitor = new ZipDirectoryVisitor(sourceDir);
    Files.walkFileTree(sourceDir, zipVisitor);
    FileOutputStream fos = new FileOutputStream(targetFile.toString());
    ZipOutputStream zos = new ZipOutputStream(fos);
    byte[] buffer = new byte[1024];
    for (ZipEntry entry : zipVisitor.getZipEntries()) {
        zos.putNextEntry(entry);
        Path curFile = Paths.get(sourceDir.getParent().toString(), entry.toString());
        if (!curFile.toFile().isDirectory()) {
            FileInputStream in = new FileInputStream(Paths.get(sourceDir.getParent().toString(), entry.toString()).toString());
            int len;
            while ((len = in.read(buffer)) > 0) {
                zos.write(buffer, 0, len);
            }
            in.close();
        }
        zos.closeEntry();
    }
    zos.close();

}

次に、ZipDirectoryVisitorの実装を示します。

class ZipDirectoryVisitor extends SimpleFileVisitor<Path> {
    private Path dirToZip;
    private List<ZipEntry> zipEntries; // files and folders inside source folder as Zip entries
    public ZipDirectoryVisitor(Path dirToZip) throws IOException {
        this.dirToZip = dirToZip;
        zipEntries = new ArrayList<>();
    }

    @Override
    public FileVisitResult visitFile(Path path, BasicFileAttributes basicFileAttributes) throws IOException {
        // According to Zip standard backslashes
        // should not be used in Zip entries
        String zipFile = dirToZip.getParent().relativize(path).toString().replace("\\", "/");
        ZipEntry entry = new ZipEntry(zipFile);
        zipEntries.add(entry);
        return FileVisitResult.CONTINUE;
    }


    @Override
    public FileVisitResult preVisitDirectory(Path path, BasicFileAttributes basicFileAttributes) throws IOException {
        String zipDir = dirToZip.getParent().relativize(path).toString().replace("\\", "/");
        // Zip directory entries should end with a forward slash
        ZipEntry entry = new ZipEntry(zipDir + "/");
        zipEntries.add(entry);
        return FileVisitResult.CONTINUE;
    }


    @Override
    public FileVisitResult visitFileFailed(Path path, IOException e) throws IOException {
        System.err.format("Could not visit file %s while creating a file list from file tree", path);
        return FileVisitResult.TERMINATE;
    }

    public List<ZipEntry> getZipEntries() {
        return zipEntries;
    }
}