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

https://www.cnblogs.com/jhxxb/p/11303947.html

上一篇:2021年度编程语言排行榜来啦,它凭什么能超过C语言,排名第一?


下一篇:20202312 2020-2021-2《数据结构与面向对象程序设计》课程总结