对于ZIP文件的解压来说,NIO提供了一个默认的文件系统:ZipFileSystem,其父类是FileSystem。
通过如下代码,如果参数path指向的是一个zip或者jar文件,则就能获取ZipFileSystem的对象。
FileSystem fs = FileSystems.newFileSystem(path, null);
Files 进行文件操作
NIO的Files提供了诸多文件操作的函数,此处解压使用其copy、createDirectories、walkFileTree来实现。
static Path copy(Path from, Path to, CopyOption... options)
static Path copy(Path from, Path to, CopyOption... options)
- 将from复制或移动到给定位置,并返回to。如果目标路径已经存在,那么复制或者移动将失败。如果想要覆盖已有的目标路径可以使用REPLACE_EXISTING选项。如果想要复制所有的文件属性,可以使用COPY_ATTRIBUTES选项。
Files.copy(fromPath,toPath,StandardCopyOption.REPLACE_EXISTING,StandardCopyOption.COPY_ATTRIBUTES)
- 将from复制或移动到给定位置,并返回to。如果目标路径已经存在,那么复制或者移动将失败。如果想要覆盖已有的目标路径可以使用REPLACE_EXISTING选项。如果想要复制所有的文件属性,可以使用COPY_ATTRIBUTES选项。
static Path createFile(Path path, FileAttribute<?>... attrs)
static Path createDirectory(Path path, FileAttribute<?>... attrs)
static Path createDirectories(Path path, FileAttribute<?>... attrs)
- 创建一个文件或目录,createDirectorIes方法还会创建路径中所有的中间目录。
文件遍历
Files提供了walkFileTree来进行目录的子孙遍历:
static Path walkFileTree(Path start, FileVisitor<? super Path> visitor)
- 便利给定路径的所有子孙,并将访问器应用于这些子孙上。
SimpleFileVisitor<T
>:
static FileVisitResult visitFile(T path, BasicFileAttributes attrs)
- 在访问文件或目录时被调用,返回CONTINUE、SKIP_SUBTREE、SKIP_SIBLINGS和TERMINATE之一,默认实现是不做任何操作而继续访问。
static FileVisitResult preVisitDirectory(T dir, BasicFileAttributes attrs)
static FileVisitResult postVisitDirectory(T dir, BasicFileAttributes attrs)
- 在访问目录之前和之后被调用,默认实现是不做任何操作而继续访问。
static FileVisitResult visitFileFailed(T path, IOException exc)
- 如果在试图获取给定文件的信息时抛出异常,则该方法被调用。默认实现是重新抛出异常,这回导致访问操作以这个异常而终止。如果你想自己访问,可以覆盖这个方法。
ZIP解压
解压zip废话不多说代码如下:
public static void decompression(String fromPathStr, String targetPathStr) throws IOException {
Path fromPath = Paths.get(fromPathStr);
final Path targetPath = Paths.get(targetPathStr);
FileSystem fs = FileSystems.newFileSystem(fromPath, null);
long startTime = System.currentTimeMillis();
Files.walkFileTree(fs.getPath("/"), new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
Files.copy(file, targetPath.resolve(file.toString().substring(1)), StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.COPY_ATTRIBUTES);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
if (dir.getParent() != null) {
if (dir.getFileName().toString().equals("__MACOSX/")) { // MAC系统压缩自带的隐藏文件过滤
return FileVisitResult.SKIP_SUBTREE;
}
Files.createDirectories(targetPath.resolve(dir.toString().substring(1)));
}
return FileVisitResult.CONTINUE;
}
});
long endTime = System.currentTimeMillis();
LOG.info("解压文件花费时间:{}", endTime - startTime + " ms");
}
其他实现
maven添加依赖:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
<version>${commons.compress.version}</version>
</dependency>
代码:
public static void decompression(String fromPathStr, String targetPathStr) throws IOException {
Long startTime = System.currentTimeMillis();
ZipArchiveInputStream inputStream = new ZipArchiveInputStream(new BufferedInputStream(new FileInputStream(fromPathStr)));
Files.createDirectories(Paths.get(targetPathStr));
ZipArchiveEntry entry = null;
while ((entry = inputStream.getNextZipEntry()) != null) {
if (entry.isDirectory()) {
Files.createDirectories(Paths.get(targetPathStr, entry.getName()));
} else {
OutputStream os = null;
try {
os = new BufferedOutputStream(new FileOutputStream(new File(targetPathStr, entry.getName())));
//输出文件路径信息
IOUtils.copy(inputStream, os);
} finally {
IOUtils.closeQuietly(os);
}
}
}
Long consumeTime = System.currentTimeMillis() - startTime;
LOG.info("压缩文件花费时间:{}", consumeTime);
}