我需要在系统中向客户提供zip文件的视图,并允许客户下载所选文件。
现在我已经记住了所有zipentry位置,但是有没有java zip工具可以解压缩zip文件的指定位置? API 就像 unzip(file, longentryStart, longentryLength);
使用 Java 7 的 NIO2 可以在不弄乱字节数组或输入流的情况下完成此操作:
public void extractFile(Path zipFile, String fileName, Path outputFile) throws IOException {
// Wrap the file system in a try-with-resources statement
// to auto-close it when finished and prevent a memory leak
try (FileSystem fileSystem = FileSystems.newFileSystem(zipFile, null)) {
Path fileToExtract = fileSystem.getPath(fileName);
Files.copy(fileToExtract, outputFile);
}
}
您可以使用以下代码从 zip 中提取特定文件:-
public static void main(String[] args) throws Exception{
String fileToBeExtracted="fileName";
String zipPackage="zip_name_with_full_path";
OutputStream out = new FileOutputStream(fileToBeExtracted);
FileInputStream fileInputStream = new FileInputStream(zipPackage);
BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream );
ZipInputStream zin = new ZipInputStream(bufferedInputStream);
ZipEntry ze = null;
while ((ze = zin.getNextEntry()) != null) {
if (ze.getName().equals(fileToBeExtracted)) {
byte[] buffer = new byte[9000];
int len;
while ((len = zin.read(buffer)) != -1) {
out.write(buffer, 0, len);
}
out.close();
break;
}
}
zin.close();
}
另请参阅此链接:如何从远程存档文件中提取单个文件?
你可以这样尝试:
ZipFile zf = new ZipFile(file);
try {
InputStream in = zf.getInputStream(zf.getEntry("file.txt"));
// ... read from 'in' as normal
} finally {
zf.close();
}
我还没有尝试过,但在 Java 7 ZipFileSystem 中你可以尝试这样从 zip 文件中提取 file.TXT 文件。
Path zipfile = Paths.get("/samples/ziptest.zip");
FileSystem fs = FileSystems.newFileSystem(zipfile, env, null);
final Path root = fs.getPath("/file.TXT");
要使用 FileSystems.newFileSystem,您需要使用 URI.create 来创建第一个参数
您需要指定正确的协议。 “罐子:文件:”
另外:你需要一个具有以下属性的 Map
map.put("create","true"); (or "false" to extract)
extract("/tmp","photos.zip","tiger.png",map)
void extract(String path, String zip, String entry, Map<String,String> map){
try (FileSystem fileSystem = FileSystems.newFileSystem(URI.create("jar:file:"+ path + "/" + zip), map)) {
Path fileToExtract = fileSystem.getPath(entry);
Path fileOutZip = Paths.get(path + "/unzipped_" + entry );
Files.copy(fileToExtract, fileOutZip);
}
}
所以我遇到了一个相关问题,但在这里没有得到完全解答。如果我在流式传输下载时只有
ZipInputStream
,如何仅提取多个特定文件。这让我抓狂,因为如果您不想将它们全部解压,那么如何获取输入流中的下一个条目并不明显。答案是递归函数。
static void caller() {
// res.body() is from java's http client, but basically wherever you get the inputstream that is a zip
try (var is = new ZipInputStream(res.body())) {
recurseExtract(is, is.getNextEntry(), dir);
}
}
static void recurseExtract(ZipInputStream is, ZipEntry entry, Path dir) throws IOException {
if (entry == null) {
return;
}
if (shouldExtract(entry.getName())) {
var path = Path.of(entry.getName());
if (path.getNameCount() > 1) {
if (entry.isDirectory() ) {
Files.createDirectory(dir.resolve(path));
}
else {
System.out.println("Extracting " + dir.resolve(noRoot));
Files.copy(is, dir.resolve(noRoot));
}
}
}
is.closeEntry(); // not certain this is necessary
recurseExtract(is, is.getNextEntry(), dir);
}
static boolean shouldExtract(String entry) {
// check for ".." to avoid zip slip security vulnerability
return ! entry.contains(".."); // put other filtering here, but check for the .. too somewhere
}
我处理过一个案例:
步骤1:我在指定目录中有zip文件需要解压
第2步:将解压后的文件(一个zip文件中的多个文件)存储在指定目录中)(注意:清理要移动解压文件的目标目录)。
这是对我有用的代码:
public String unZip(String zipFilePath, String destDirectory, String afilename) {
String efilename; String[] files; String unzipfilePath; String[] oldFiles;
File destDir = new File(destDirectory);
if (destDir.isDirectory()) {
oldFiles = destDir.list();
for (int k = 0; k < oldFiles.length; k++) {
File oFiles = new File(oldFiles[k]);
logMessage("Old file name in the unziped folder is "+oFiles );
oFiles.delete();
}
}
if (!destDir.exists()) {
destDir.mkdir();
}
ZipInputStream zipIn;
try {
zipIn = new ZipInputStream(new FileInputStream(zipFilePath));
ZipEntry entry = zipIn.getNextEntry();
// iterates over entries in the zip file
while (entry != null) {
unzipfilePath = destDirectory + File.separator + entry.getName();
if (!entry.isDirectory()) {
// if the entry is a file, extracts it
extractFile(zipIn, unzipfilePath);
logMessage(" File copied to Unziped folder is " +unzipfilePath);
} else {
// if the entry is a directory, make the directory
File dir = new File(unzipfilePath);
dir.mkdir();
}
zipIn.closeEntry();
entry = zipIn.getNextEntry();
}
zipIn.close();
// check for filename in the unzipped folder
File dest = new File(destDirectory);
files = dest.list();
int flag = 0;
if (files == null) {
logMessage("Empty directory.");
}
else {
// Linear search in the array forf expected file name
for (int i = 0; i < files.length; i++) {
efilename = files[i];
if (efilename.equals(afilename))
logMessage(efilename + " Expected File found in Unziped files folder");
flag = 1;
Assert.assertNotNull(efilename);
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return efilename;
}