如何使用 java 压缩文件夹本身

假设我有以下目录结构。

D:\reports\january\

在一月内假设有两个 excel 文件分别是 A.xls 和 B.xls。有很多地方都写过如何使用 java.util.zip压缩文件。但是我想压缩1月文件夹本身在报告文件夹中,这样 一月一月,闭嘴都将在报告中出现。(这意味着当我解压缩 january.zip 文件时,我应该得到 January 文件夹 ).

有人可以提供我的代码,使用 java.util.zip做到这一点。请让我知道是否可以更容易地做到这一点,使用其他库。

非常感谢。

172504 次浏览

我会使用 阿帕奇蚂蚁,它有一个 API 来从 Java 代码而不是从 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();

在这里,我告诉它从基本目录 D:\reports开始,压缩 january文件夹及其中的所有内容。结果 zip 文件中的路径将与相对于 D:\reports的原始路径相同,因此它们将包含 january前缀。

你试过 零转弯,零点库吗? 它真的很棒! 压缩一个文件夹只是一行:

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

(感谢 Oleg Elajev的例子)

我通常使用一个我曾经为这个任务编写的 helper 类:

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

它可以很容易地解决包 java.util.Zip不需要任何额外的 Jar文件

只要复制以下代码和 run it与您的 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());
}
}

参考 Mkyong。我改变了当前问题的要求的代码

Java7 + ,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);
}
}
}
}

试试这个:

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






}

以下是 Java8 + 的例子:

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

下面是一个非常简洁的 Java7 + 解决方案,它完全依赖于普通的 JDK 类,不需要第三方库:

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创建压缩文件。

Java6 +

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


}

我发现这个解决方案对我来说非常好用。不需要任何第三方 API

‘ test’实际上是一个文件夹,里面会有很多文件。

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

此方法压缩文件夹并将所有子文件和文件夹(包括空文件夹)添加到压缩文件中。

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

增强的 Java8 + 示例(从 Nikita Koksharov 的回答分叉)

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.walk被封装在 try with resources块中,这样流就可以被关闭。这解决了由 SonarQube识别的阻塞问题。 谢谢@Matt Harrison 指出这一点。

使用 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");

我已经修改了上面的解决方案,并用 Files.list代替了 Files.walk。这还假设您正在压缩的目录只包含文件,而不包含任何子目录。

private void zipDirectory(Path dirPath) throws IOException {
String zipFilePathStr = dirPath.toString() + ".zip";
Path zipFilePath = Files.createFile(Paths.get(zipFilePathStr));


try (ZipOutputStream zs = new ZipOutputStream(Files.newOutputStream(zipFilePath))) {
Files.list(dirPath)
.filter(filePath-> !Files.isDirectory(filePath))
.forEach(filePath-> {
ZipEntry zipEntry = new ZipEntry(dirPath.relativize(filePath).toString());
try {
zs.putNextEntry(zipEntry);
Files.copy(filePath, zs);
zs.closeEntry();
}
catch (IOException e) {
System.err.println(e);
}
});
}
}

改进@Nikita Koksharov 的代码时遇到了打包空目录的问题。

private void zipDirectory(OutputStream outputStream, Path directoryPath) throws IOException {
try (ZipOutputStream zs = new ZipOutputStream(outputStream)) {
Path pp = directoryPath;
Files.walk(pp)
.forEach(path -> {
try {
if (Files.isDirectory(path)) {
zs.putNextEntry(new ZipEntry(pp.relativize(path).toString() + "/"));
} else {
ZipEntry zipEntry = new ZipEntry(pp.relativize(path).toString());
zs.putNextEntry(zipEntry);
Files.copy(path, zs);
zs.closeEntry();
}
} catch (IOException e) {
System.err.println(e);
}
});
}
}

测试用法

    FileOutputStream zipOutput = new FileOutputStream("path_to_file.zip");
Path pathOutput = Path.of("path_directory_fid");
zipDirectory(outputStream, pathOutput);

试试这个 zip (“ C: testFolder”,“ D: testZip.zip”)

public void zip( String sourcDirPath,  String zipPath) throws IOException {
Path zipFile = Files.createFile(Paths.get(zipPath));


Path sourceDirPath = Paths.get(sourcDirPath);
try (ZipOutputStream zipOutputStream = new ZipOutputStream(Files.newOutputStream(zipFile));
Stream<Path> paths = Files.walk(sourceDirPath)) {
paths
.filter(path -> !Files.isDirectory(path))
.forEach(path -> {
ZipEntry zipEntry = new ZipEntry(sourceDirPath.relativize(path).toString());
try {
zipOutputStream.putNextEntry(zipEntry);
Files.copy(path, zipOutputStream);
zipOutputStream.closeEntry();
} catch (IOException e) {
System.err.println(e);
}
});
}


System.out.println("Zip is created at : "+zipFile);
}