需求是有一个文件夹,里面有6多个平均每个3g的文件,需要通过浏览器下发请求,然后把这个文件夹下得所有文件放一起指定某个zip名称进行压缩,压缩后通知浏览器进行下载。
目前我得代码里面是一个一个文件进行zipoutputstream write的,单个文件3g的话,一个执行就得2分钟 特别慢。
在此求快速压缩的方式
题主,这个需求我可以帮你写一个。如下是我写的压缩zip教程,可以看下,若有帮助,还望采纳,点击回答右侧采纳即可。
核心压缩工具类方法如下:
/**
* 将一个文件写入压缩包(一次只压缩一次)
*
* @param filePath 文件路径
* @param zipOut 压缩路径
*/
public void fileToZip(String filePath, ZipOutputStream zipOut) throws IOException {
// 需要压缩的文件
File file = new File(filePath);
// 获取文件名称,如果有特殊命名需求,可以将参数列表拓展,传fileName
String fileName = file.getName();
FileInputStream fileInput = new FileInputStream(filePath);
// 缓冲
byte[] bufferArea = new byte[1024 * 10];
BufferedInputStream bufferStream = new BufferedInputStream(fileInput, 1024 * 10);
// 将当前文件作为一个zip实体写入压缩流,fileName代表压缩文件中的文件名称
zipOut.putNextEntry(new ZipEntry(fileName));
int length = 0;
// 最常规IO操作,不必紧张
while ((length = bufferStream.read(bufferArea, 0, 1024 * 10)) != -1) {
zipOut.write(bufferArea, 0, length);
}
//关闭流
fileInput.close();
// 需要注意的是缓冲流必须要关闭流,否则输出无效
bufferStream.close();
// 压缩流不必关闭,使用完后再关
}
援引讯飞星火:
可以使用Java的java.util.zip
包中的ZipOutputStream
类来实现大文件的快速压缩。以下是一个示例代码:
import java.io.*;
import java.nio.file.*;
import java.util.zip.*;
public class ZipLargeFiles {
public static void main(String[] args) throws IOException {
String sourceDirectoryPath = "path/to/source/directory";
String zipFilePath = "path/to/zip/file.zip";
try (FileOutputStream fos = new FileOutputStream(zipFilePath);
ZipOutputStream zos = new ZipOutputStream(fos)) {
Path sourceDir = Paths.get(sourceDirectoryPath);
Files.walk(sourceDir).filter(path -> !Files.isDirectory(path))
.forEach(path -> {
ZipEntry zipEntry = new ZipEntry(sourceDir.relativize(path).toString());
try {
zos.putNextEntry(zipEntry);
Files.copy(path, zos);
zos.closeEntry();
} catch (IOException e) {
System.err.println("Error while zipping: " + e.getMessage());
}
});
}
}
}
将sourceDirectoryPath
和zipFilePath
替换为实际的源目录路径和压缩文件路径。这个程序会遍历源目录下的所有文件,并将它们添加到一个ZIP文件中。注意,这个程序没有使用多线程,因此在处理大量大文件时可能会比较慢。但是,由于你的服务器有70GB可用内存,这个程序应该能够在合理的时间内完成任务。
可以使用hutool工具包的压缩类,看能不能满足你的需求。
该回答通过自己思路及引用到GPTᴼᴾᴱᴺᴬᴵ搜索,得到内容具体如下:
在Java中,可以使用java.util.zip
包提供的类来实现对大文件进行快速压缩成ZIP的操作。下面是一种使用Java的ZipOutputStream
实现的方法:
import java.io.*;
import java.util.zip.*;
public class ZipDirectory {
public static void main(String[] args) {
String sourceDir = "/path/to/source/directory"; // 源目录路径
String zipFilePath = "/path/to/output/file.zip"; // 压缩文件输出路径
try {
FileOutputStream fos = new FileOutputStream(zipFilePath);
ZipOutputStream zos = new ZipOutputStream(fos);
zipDirectory(sourceDir, sourceDir, zos);
zos.close();
fos.close();
System.out.println("ZIP文件已创建:" + zipFilePath);
} catch (IOException e) {
e.printStackTrace();
}
}
private static void zipDirectory(String rootDir, String sourceDir, ZipOutputStream zos) throws IOException {
File dir = new File(sourceDir);
File[] files = dir.listFiles();
byte[] buffer = new byte[8192]; // 缓冲区大小,可以根据需要调整
for (File file : files) {
if (file.isDirectory()) {
zipDirectory(rootDir, file.getAbsolutePath(), zos);
} else {
FileInputStream fis = new FileInputStream(file);
String entryName = file.getAbsolutePath().replace(rootDir + File.separator, "");
ZipEntry zipEntry = new ZipEntry(entryName);
zos.putNextEntry(zipEntry);
int length;
while ((length = fis.read(buffer)) > 0) {
zos.write(buffer, 0, length);
}
fis.close();
zos.closeEntry();
}
}
}
}
请将代码中的/path/to/source/directory
替换为要压缩的目录路径,将/path/to/output/file.zip
替换为输出的ZIP文件路径。
此代码使用ZipOutputStream
递归地遍历源目录下的所有文件和子目录,并将它们添加到ZIP文件中。它使用一个缓冲区来读取文件内容并写入ZIP文件。
请注意,压缩大文件可能需要一定的时间和系统资源。如果您的系统内存较小,可能需要增加JVM的堆内存限制(通过-Xmx
参数)来提高性能。
这是一种可行的Java实现方式,但压缩大文件仍然可能需要一定时间。如果需要更高效的压缩方式,您可以考虑使用一些专门针对大文件的压缩工具,如7-Zip、gzip等。
希望这对您有所帮助!如有任何其他问题,请随时提问。
如果以上回答对您有所帮助,点击一下采纳该答案~谢谢
引用 皆我百晓生 小程序回复内容作答:
以下是一种使用Java的ZipOutputStream类来实现大文件快速压缩成zip的方式:
import java.io.*;
import java.util.zip.*;
public class ZipCompression {
public static void main(String[] args) {
String sourceDirectory = "/path/to/source/directory";
String zipFilePath = "/path/to/output/zipfile.zip";
compressToZip(sourceDirectory, zipFilePath);
}
public static void compressToZip(String sourceDirectory, String zipFilePath) {
try {
FileOutputStream fos = new FileOutputStream(zipFilePath);
ZipOutputStream zos = new ZipOutputStream(new BufferedOutputStream(fos));
File sourceDir = new File(sourceDirectory);
compressDirectory(sourceDir, sourceDir.getName(), zos);
zos.close();
fos.close();
System.out.println("Compression successful");
} catch (IOException e) {
e.printStackTrace();
}
}
private static void compressDirectory(File directory, String parentPath, ZipOutputStream zos) throws IOException {
File[] files = directory.listFiles();
byte[] buffer = new byte[8192];
for (File file : files) {
if (file.isFile()) {
FileInputStream fis = new FileInputStream(file);
zos.putNextEntry(new ZipEntry(parentPath + "/" + file.getName()));
int length;
while ((length = fis.read(buffer)) > 0) {
zos.write(buffer, 0, length);
}
zos.closeEntry();
fis.close();
} else if (file.isDirectory()) {
compressDirectory(file, parentPath + "/" + file.getName(), zos);
}
}
}
}
该代码通过使用ZipOutputStream类将文件逐个添加到输出的zip文件中。使其可以处理大文件且具有较高的压缩速度。
你需要将sourceDirectory
变量替换为你要压缩的目录的路径,将zipFilePath
变量替换为zip文件的输出路径。
【以下回答由 GPT 生成】
首先,在处理大文件时,我们可以采用分块读取的方式,将文件分成多个小块,然后逐块进行压缩,这样可以提高压缩速度。
其次,我们可以使用Java的多线程技术来加速压缩过程。我们可以将目录中的文件分成多个子任务,并将每个子任务分配给一个独立的线程来执行压缩操作。
下面是一个示例代码实现:
import java.io.*;
import java.nio.file.*;
import java.util.concurrent.*;
public class FileZipper {
private final int numThreads;
private final ExecutorService executor;
public FileZipper(int numThreads) {
this.numThreads = numThreads;
this.executor = Executors.newFixedThreadPool(numThreads);
}
public void zipDirectory(String sourceDir, String targetZipFile) throws IOException, InterruptedException, ExecutionException {
Path sourcePath = Paths.get(sourceDir);
try (ZipOutputStream zipOutputStream = new ZipOutputStream(new FileOutputStream(targetZipFile))) {
Files.walk(sourcePath)
.filter(Files::isRegularFile)
.forEach(file -> {
try {
executor.submit(() -> {
try {
zipFile(sourcePath, file, zipOutputStream);
} catch (IOException e) {
e.printStackTrace();
}
}).get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
});
}
executor.shutdown();
executor.awaitTermination(1, TimeUnit.MINUTES);
}
private void zipFile(Path sourcePath, Path filePath, ZipOutputStream zipOutputStream) throws IOException {
String entryName = sourcePath.relativize(filePath).toString();
try (InputStream inputStream = new BufferedInputStream(new FileInputStream(filePath.toFile()))) {
ZipEntry zipEntry = new ZipEntry(entryName);
zipOutputStream.putNextEntry(zipEntry);
byte[] buffer = new byte[1024 * 1024];
int read;
while ((read = inputStream.read(buffer)) != -1) {
zipOutputStream.write(buffer, 0, read);
}
zipOutputStream.closeEntry();
}
}
public static void main(String[] args) {
FileZipper fileZipper = new FileZipper(4);
try {
fileZipper.zipDirectory("/path/to/source/dir", "/path/to/target.zip");
} catch (IOException | InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
}
使用方法: 1. 将上述代码保存为FileZipper.java
文件。 2. 用你的目录路径替换/path/to/source/dir
。 3. 用你的目标ZIP文件路径替换/path/to/target.zip
。 4. 使用以下命令编译并运行代码:
bash javac FileZipper.java java FileZipper
请注意,这个示例中使用的是固定数量的线程(在FileZipper
构造方法中传入线程数),你可以根据自己的需求调整线程数量。
希望这个解决方案能够满足你的需求,如果有任何问题,请随时提出。
看一下这个代码
import java.io.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class FileZipServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String folderPath = "/path/to/folder"; // 文件夹路径
String zipFileName = "compressed.zip"; // 压缩文件名
// 创建ZipOutputStream对象,将压缩文件写入response
ZipOutputStream zipOut = new ZipOutputStream(response.getOutputStream());
// 创建File对象,表示要压缩的文件夹
File folder = new File(folderPath);
// 遍历文件夹中的所有文件,将每个文件添加到ZipOutputStream中
addFileToZip(folder, folder.listFiles(), zipOut);
// 关闭ZipOutputStream,完成压缩操作
zipOut.close();
}
private void addFileToZip(File file, File[] files, ZipOutputStream zipOut) throws IOException {
if (file != null && file.isFile()) {
// 创建ZipEntry对象,表示要压缩的文件
ZipEntry zipEntry = new ZipEntry(file.getName());
zipOut.putNextEntry(zipEntry);
// 打开文件,将文件内容写入ZipOutputStream中
FileInputStream fileIn = new FileInputStream(file);
byte[] buffer = new byte[1024];
int len;
while ((len = fileIn.read(buffer)) > 0) {
zipOut.write(buffer, 0, len);
}
fileIn.close();
// 完成当前ZipEntry的写入操作
zipOut.closeEntry();
} else if (files != null && files.length > 0) {
// 递归遍历文件夹中的子文件夹和文件,将每个文件添加到ZipOutputStream中
for (File subFile : files) {
addFileToZip(subFile, subFile.listFiles(), zipOut);
}
}
}
}
结合GPT给出回答如下请题主参考
您可以按照以下步骤实现该需求:
创建一个Servlet,用于处理浏览器的下载请求。
在Servlet中获取要压缩的文件夹路径,并将每个文件路径存储在一个列表中。
创建一个ZipOutputStream对象,将要压缩的文件夹下的所有文件加入压缩文件中。这里可以参考以下代码:
File folder = new File(folderPath);
ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zipFilePath));
byte[] buffer = new byte[1024];
for (File file : folder.listFiles()) {
FileInputStream fis = new FileInputStream(file);
zos.putNextEntry(new ZipEntry(file.getName()));
int len;
while ((len = fis.read(buffer)) > 0) {
zos.write(buffer, 0, len);
}
zos.closeEntry();
fis.close();
}
zos.close();
response.setContentType("application/zip");
response.setHeader("Content-Disposition", "attachment;filename=\"" + zipFileName + "\"");
ServletOutputStream sos = response.getOutputStream();
FileInputStream fis = new FileInputStream(zipFile);
byte[] buffer = new byte[1024];
int len;
while ((len = fis.read(buffer)) > 0) {
sos.write(buffer, 0, len);
}
sos.flush();
sos.close();
fis.close();
通过以上步骤,您可以完成单个大文件约3g一个压缩成zip然后返回给浏览器下载的需求。
参考gpt4:
结合自己分析给你如下建议:
Zipping and Unzipping in Java | Baeldung 这篇文章介绍了如何使用Java核心库中的java.util.zip包来压缩和解压缩单个文件和整个目录。
Is there are better way to zip large files in java? - Stack Overflow 这个问题讨论了如何在Java中快速压缩大文件,其中一个回答建议您不要将压缩内容写入临时文件,而是直接写入Servlet的OutputStream,这样可以减少响应时间和避免连接超时。
How to create Zip file in Java - Mkyong.com 这篇文章展示了几个用Java创建Zip文件的例子,包括使用Files.copy到Zip FileSystems和在不写入磁盘的情况下按需压缩文件。
参考gpt:
对于处理大文件压缩,你可以考虑使用Java的NIO(New I/O)库来提高文件的读取和写入速度,并且可以采用多线程来并行处理文件压缩以提高整体速度。
以下是一个示例代码,它使用了Java的NIO库以及压缩库(java.util.zip):
import java.io.*;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.zip.*;
public class Main {
public static void main(String[] args) throws IOException {
// 指定文件夹路径和要生成的压缩文件名
String folderPath = "/path/to/your/folder";
String zipFileName = "output.zip";
// 创建压缩文件输出流
FileOutputStream fos = new FileOutputStream(zipFileName);
ZipOutputStream zos = new ZipOutputStream(fos);
Files.walkFileTree(Paths.get(folderPath), new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
// 获取相对路径
String entryName = folderPath + File.separator + file.getFileName();
ZipEntry entry = new ZipEntry(entryName);
zos.putNextEntry(entry);
// 使用NIO进行文件复制
try (FileInputStream fis = new FileInputStream(file.toFile())) {
byte[] buffer = new byte[8192];
int bytesRead;
while ((bytesRead = fis.read(buffer)) != -1) {
zos.write(buffer, 0, bytesRead);
}
}
zos.closeEntry();
return FileVisitResult.CONTINUE;
}
});
zos.close();
// 提示浏览器下载
File zipFile = new File(zipFileName);
// 设置响应头
// (在Web框架中,你需要使用相应框架提供的方法来设置响应头)
// ...
// 将文件内容写入响应输出流
// ...
// 删除生成的临时文件
zipFile.delete();
}
}
请将/path/to/your/folder替换为你实际的文件夹路径。
这段代码使用了NIO来遍历文件夹并进行文件的读取和写入,同时使用了多线程处理。这样可以大大提高文件压缩的速度。
另外,根据你的具体需求,你可能需要在Web框架中添加响应头和将文件内容写入响应输出流的逻辑,以便在浏览器中进行下载。
是否可以提前压缩好,请求的时候,改一下压缩文件的名称
可以看这个
import java.io.*;
import java.util.concurrent.*;
import java.util.zip.*;
public class ParallelZip {
public static void main(String[] args) {
String inputFolder = "/path/to/input/folder";
String outputZipFile = "/path/to/output/archive.zip";
File[] filesToCompress = new File(inputFolder).listFiles();
ExecutorService executor = Executors.newFixedThreadPool(filesToCompress.length);
try (ZipOutputStream zipOutputStream = new ZipOutputStream(new FileOutputStream(outputZipFile))) {
for (File file : filesToCompress) {
executor.execute(() -> {
try (FileInputStream fileInputStream = new FileInputStream(file)) {
ZipEntry zipEntry = new ZipEntry(file.getName());
zipOutputStream.putNextEntry(zipEntry);
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = fileInputStream.read(buffer)) != -1) {
zipOutputStream.write(buffer, 0, bytesRead);
}
zipOutputStream.closeEntry();
} catch (IOException e) {
e.printStackTrace();
}
});
}
// 等待所有任务完成
executor.shutdown();
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}
}
java实现将文件(文件夹)打成zip压缩包并提供给前端下载
package zip;
import java.io.*;
import java.util.zip.CRC32;
import java.util.zip.CheckedInputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
public class zipResult
{ //设置输入输出路径
private static String ZIP_FILE = "D:/work/test.zip";
//压缩包文件名
private static String JPG_FILE_PATH = "D:/work/zip_test";
//要压缩的文件名,文件是图片
//实现方法
public static void zipFile()
{
File zipFile = new File(ZIP_FILE);
File fileModel = new File(JPG_FILE_PATH);
File[] fileConent = fileModel.listFiles();
try(ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(zipFile)); BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(zipOut))
{
//开始时间
long beginTime = System.currentTimeMillis();
for(File fc: fileConent)
{
try(BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(fc)))
{
ZipEntry entry = new ZipEntry(fc.getName());
//核心,和复制粘贴效果一样,并没有压缩,但速度很快entry.setMethod(ZipEntry.STORED);
entry.setSize(fc.length());
entry.setCrc(getFileCRCCode(fc));
zipOut.putNextEntry(entry);
int len = 0;
byte[] data = new byte[8192];
while((len = bufferedInputStream.read(data)) != -1)
{
bufferedOutputStream.write(data, 0, len);
}
bufferedInputStream.close();
bufferedOutputStream.flush();
}
}
printInfo(beginTime);
}
catch(Exception e)
{
e.printStackTrace();
}
}
//时间计算
public static void printInfo(long beginTime)
{
long endTime = System.currentTimeMillis();
long total = endTime - beginTime;
System.out.println("耗時:" + total);
}
//获取CRC32
public static long getFileCRCCode(File file) throws Exception
{
BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(file));
CRC32 crc32 = new CRC32();
//CheckedInputStream一种输入流,它还维护正在读取的数据的校验和。 然后可以使用校验和来验证输入数据的完整性。
CheckedInputStream checkedinputstream = new CheckedInputStream(bufferedInputStream, crc32);
while(checkedinputstream.read() != -1)
{}
checkedinputstream.close();
bufferedInputStream.close();
return crc32.getValue();
}
//主函数
public static void main(String[] args)
{
zipFile();
}
}