Java7 的文件API可以把zip、jar文件看作是一个文件系统,访问文件系统都可以使用Path及相关的类进行。
下面是创建zip压缩文件的示例:
private static void create() {
Map<String, String> env = new HashMap<>();
env.put("create", "true"); // 如果zip文件不存在则创建
// 父目录的文件夹必须已创建,否则抛出异常。zip文件可以未创建
URI uri = URI
.create("jar:file:/H:/java/learn/java7/zipfilesystem/testzipfs.zip");
try (FileSystem zipfs = FileSystems.newFileSystem(uri, env);) {
Path externalPath = Paths.get("H:/java/jdk7/COPYRIGHT");
// 创建zip文件里的目录
Path zipDir = zipfs.getPath("abc/xyz");
Files.createDirectories(zipDir);
System.out.println("zipDir: " + zipDir);
// 路径必须是已创建。
Path contentFile = zipfs.getPath("abc/xyz", "copyRight");
Files.copy(externalPath, contentFile);
} catch (IOException e) {
e.printStackTrace();
}
}
这个代码片段也展示了Java7的其他一些特性:
1、泛型的简写: Map<String, String> env = new HashMap<> ();
2、try-with-closeable:try (FileSystem zipfs = FileSystems.newFileSystem(uri, env);) {
FileSystem类实现了Closeable类,不再需要手动显示关闭。
在目前的测试中发现,如果要压缩有层次结构的文件时,如zip里有目录:abc/xyz/123.txt,需要预先建立abc/xyz目录,否则会抛出异常。 Map参数里的create属性为true只表示最后的那个文件(123.txt)不存在时创建。
这好像还不如ZipFile与ZipEntry的组合好用。
有了FileSystem实例后,就可以像访问本地的文件系统一样简单。下面的代码解压前面建立的zip文件里的文件到本地目录。
下面的代码实现了FileVisitor接口,把指定zip的path下的内容解压到saveDir的对应目录下:
private static void walkZipPath(final String saveDir, Path path)
throws IOException {
FileVisitor<Path> fv = new FileVisitor<Path>() {
@Override
public FileVisitResult preVisitDirectory(Path dir,
BasicFileAttributes attrs) throws IOException {
// 创建本地目录
new File(saveDir, dir.toString()).mkdirs();
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFile(Path file,
BasicFileAttributes attrs) throws IOException {
// 创建本地文件路径
Path Localtarget = Paths.get(saveDir, file.toString());
// 拷贝到本地文件系统
Files.copy(file, Localtarget,
StandardCopyOption.REPLACE_EXISTING);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFileFailed(Path file, IOException exc)
throws IOException {
exc.printStackTrace();
return FileVisitResult.TERMINATE;
}
@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc)
throws IOException {
// 不为空表示出错
if (exc != null) {
exc.printStackTrace();
return FileVisitResult.TERMINATE;
}
return FileVisitResult.CONTINUE;
}
};
Files.walkFileTree(path, fv);
}
下面的代码根据zip文件建立一个新的文件系统,并进行访问:
private static void extractZip() {
String uri = "H:/java/learn/java7/zipfilesystem/testzipfs.zip";
Path path = Paths.get(uri);
String saveDir = "H:/java/learn/java7/zipfilesystem";
try (FileSystem fs = FileSystems.newFileSystem(path, null);) {
for (Path path2 : fs.getRootDirectories()) {
walkZipPath(saveDir, path2);
}
} catch (IOException e) {
e.printStackTrace();
}
}
java7的新的文件API与Apache Commons IO包的功有很多相似的地方。