ZipInputStream - 解压缩文件的功能方法
ZipInputStream - functional approach to unzip files
我有一个只包含文件而不包含目录的 zip 文件。我想仅使用功能 Java.
将文件解压缩到目录中
下面的代码按预期工作并将文件解压缩到目标文件夹中。
public static void unzip(Path source, Path target) throws IOException {
try (ZipInputStream zis = new ZipInputStream(new FileInputStream(source.toFile()))) {
ZipEntry zipEntry = zis.getNextEntry();
while (zipEntry != null) {
Path targetDirResolved = target.resolve(zipEntry.getName());
Path normalizePath = targetDirResolved.normalize();
if (!normalizePath.startsWith(target)) {
throw new IOException("Bad zip entry: " + zipEntry.getName());
}
Files.copy(zis, normalizePath, StandardCopyOption.REPLACE_EXISTING);
zipEntry = zis.getNextEntry();
}
zis.closeEntry();
}
}
我想实现与上面相同的功能,但使用更实用的方法。
我最初的想法是将 while 循环转换成类似 IntStream.range(0, )....
的东西,但不知道 zip 文件中的条目数。
有什么想法吗?
消除 while 循环的一种方法是使用 ZipFile
stream:
try (ZipFile fs = new ZipFile(source.toFile())) {
fs.stream()
.filter(Predicate.not(ZipEntry::isDirectory))
// etc
.forEach(System.out::println);
}
您还可以查看带有 Files.find
的 ZIP 文件系统,以提供合适的 Stream
ZIP 条目(一级文件),如果需要,在流而不是 forEach
,如下所示:
try (FileSystem fs = FileSystems.newFileSystem(source)) {
for (Path root : fs.getRootDirectories()) {
try (Stream<Path> stream = Files.find(root, 1, (p,a) -> a.isRegularFile())) {
stream.forEach(p -> copy(p, Path.of(target.toString(), p.toString())));
}
}
}
不幸的是,上面仍然对根目录使用正常循环,copy
是处理 IOException
:
的单独方法
private static void copy(Path from, Path to) {
try {
Files.copy(from, to, StandardCopyOption.REPLACE_EXISTING);
}
catch (IOException e) {
throw new UncheckedIOException(e);
}
}
我有一个只包含文件而不包含目录的 zip 文件。我想仅使用功能 Java.
将文件解压缩到目录中下面的代码按预期工作并将文件解压缩到目标文件夹中。
public static void unzip(Path source, Path target) throws IOException {
try (ZipInputStream zis = new ZipInputStream(new FileInputStream(source.toFile()))) {
ZipEntry zipEntry = zis.getNextEntry();
while (zipEntry != null) {
Path targetDirResolved = target.resolve(zipEntry.getName());
Path normalizePath = targetDirResolved.normalize();
if (!normalizePath.startsWith(target)) {
throw new IOException("Bad zip entry: " + zipEntry.getName());
}
Files.copy(zis, normalizePath, StandardCopyOption.REPLACE_EXISTING);
zipEntry = zis.getNextEntry();
}
zis.closeEntry();
}
}
我想实现与上面相同的功能,但使用更实用的方法。
我最初的想法是将 while 循环转换成类似 IntStream.range(0, )....
的东西,但不知道 zip 文件中的条目数。
有什么想法吗?
消除 while 循环的一种方法是使用 ZipFile
stream:
try (ZipFile fs = new ZipFile(source.toFile())) {
fs.stream()
.filter(Predicate.not(ZipEntry::isDirectory))
// etc
.forEach(System.out::println);
}
您还可以查看带有 Files.find
的 ZIP 文件系统,以提供合适的 Stream
ZIP 条目(一级文件),如果需要,在流而不是 forEach
,如下所示:
try (FileSystem fs = FileSystems.newFileSystem(source)) {
for (Path root : fs.getRootDirectories()) {
try (Stream<Path> stream = Files.find(root, 1, (p,a) -> a.isRegularFile())) {
stream.forEach(p -> copy(p, Path.of(target.toString(), p.toString())));
}
}
}
不幸的是,上面仍然对根目录使用正常循环,copy
是处理 IOException
:
private static void copy(Path from, Path to) {
try {
Files.copy(from, to, StandardCopyOption.REPLACE_EXISTING);
}
catch (IOException e) {
throw new UncheckedIOException(e);
}
}