Java ZipUtil
Zip 压缩工具类,不支持压缩空文件夹。
简单版
import java.io.FileOutputStream; import java.io.IOException; import java.nio.file.*; import java.nio.file.attribute.BasicFileAttributes; import java.time.Instant; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; public class ZipUtil { public static void main(String[] args) { zipCompression("D:\\123.zip", "D:\\123", "D:\\456", "D:\\er4.zip"); } static void zipCompression(String zipPath, String... paths) { Path[] ps = new Path[paths.length]; for (int i = 0; i < paths.length; i++) { ps[i] = Paths.get(paths[i]); } zipCompression(Paths.get(zipPath), ps); } static void zipCompression(Path zipPath, Path... paths) { long beginTime = Instant.now().toEpochMilli(); try (ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zipPath.toFile()))) { for (Path path : paths) { Files.walkFileTree(path, new SimpleFileVisitor<Path>() { @Override // 访问一个文件 public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { zos.putNextEntry(new ZipEntry(file.toString().replace(path.getParent().toString(), ""))); Files.copy(file, zos); zos.closeEntry(); return FileVisitResult.CONTINUE; } }); } } catch (IOException e) { e.printStackTrace(); } System.out.println("耗时:" + (Instant.now().toEpochMilli() - beginTime)); } }
内存映射+管道+异步线程版,效率似乎没有什改变。。。。。。
import java.io.*; import java.nio.ByteBuffer; import java.nio.MappedByteBuffer; import java.nio.channels.Channels; import java.nio.channels.FileChannel; import java.nio.channels.Pipe; import java.nio.channels.WritableByteChannel; import java.nio.file.*; import java.nio.file.attribute.BasicFileAttributes; import java.time.Instant; import java.util.concurrent.CompletableFuture; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; public class ZipUtil { public static void main(String[] args) { zipCompression("D:\\123.zip", "D:\\123", "D:\\456", "D:\\er4.zip"); } static void zipCompression(String zipPath, String... paths) { Path[] ps = new Path[paths.length]; for (int i = 0; i < paths.length; i++) { ps[i] = Paths.get(paths[i]); } zipCompression(Paths.get(zipPath), ps); } static void zipCompression(Path zipPath, Path... paths) { long beginTime = Instant.now().toEpochMilli(); try (FileOutputStream fileOutputStream = new FileOutputStream(zipPath.toFile()); WritableByteChannel out = Channels.newChannel(fileOutputStream)) { Pipe pipe = Pipe.open(); // 异步任务往通道中塞入数据 CompletableFuture.runAsync(() -> runCompressionTask(pipe, paths)); // 读取通道中数据 Pipe.SourceChannel source = pipe.source(); ByteBuffer buffer = ByteBuffer.allocate(2048); // ByteBuffer buffer = ByteBuffer.allocateDirect(2048); while (source.read(buffer) >= 0) { buffer.flip(); out.write(buffer); buffer.clear(); } } catch (IOException e) { e.printStackTrace(); } System.out.println("耗时:" + (Instant.now().toEpochMilli() - beginTime)); } // 异步任务 public static void runCompressionTask(Pipe pipe, Path... paths) { try (Pipe.SinkChannel sink = pipe.sink(); OutputStream os = Channels.newOutputStream(sink); ZipOutputStream zos = new ZipOutputStream(os); WritableByteChannel out = Channels.newChannel(zos)) { for (Path path : paths) { Files.walkFileTree(path, new SimpleFileVisitor<Path>() { @Override // 访问一个目录 public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { if (dir.toFile().list().length == 0) { // 无法打包空文件夹 // zos.putNextEntry(new ZipEntry(dir.toString().replace(path.getParent().toString(), "") + File.separator)); // System.out.println(dir.toString().replace(path.getParent().toString(), "") + File.separator); // zos.closeEntry(); } return FileVisitResult.CONTINUE; } @Override // 访问一个文件 public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { zos.putNextEntry(new ZipEntry(file.toString().replace(path.getParent().toString(), ""))); MappedByteBuffer mappedByteBuffer = new RandomAccessFile(file.toFile(), "r").getChannel().map(FileChannel.MapMode.READ_ONLY, 0, attrs.size()); out.write(mappedByteBuffer); // FileChannel fileChannel = new FileInputStream(file.toFile()).getChannel(); // fileChannel.transferTo(0, fileChannel.size(), out); // fileChannel.close(); zos.closeEntry(); return FileVisitResult.CONTINUE; } }); } zos.finish(); } catch (IOException e) { e.printStackTrace(); } } }
用到了 NIO 相关特性
https://juejin.im/post/5d5626cdf265da03a65312be
https://www.cnblogs.com/jhxxb/p/11272727.html