Reputation: 153
I am trying to unzip specific files from a zip. I first get a ZipInputStream
:
ZipInputStream zipIn = new ZipInputStream(new BufferedInputStream(new FileInputStream(filePath)));
Alright, this works! Now I want to extract two files, called F1 and F2, so I call
extractFileFromZip(zipIn, Path + "F1", "F1")
extractFileFromZip(zipIn, Path + "F2", "F2")
public static boolean extractFileFromZip(ZipInputStream inZip, String file, String name) throws Exception {
byte data[] = new byte[BUFFER_SIZE];
boolean found = false;
ZipEntry ze;
while((ze = inZip.getNextEntry()) != null) {
if(ze.getName().equals(name)) {
found = true;
// delete old file first
File oldFile = new File(file);
if(oldFile.exists()) {
if(!oldFile.delete()) {
throw new Exception("Could not delete " + file);
}
}
FileOutputStream outFile = new FileOutputStream(file);
int count = 0;
while((count = inZip.read(data)) != -1) {
outFile.write(data, 0, count);
}
outFile.close();
//inZip.closeEntry();
}
}
return true;
}
Now the problem is with inZip.getNextEntry()
. For F1 it will cycle through all the files correctly and then give null
. But for F2, it will just give null
.
Why does this happen?
Upvotes: 0
Views: 2845
Reputation: 159135
You're scanning the entire stream, consuming it. When you try to do it the second time, the stream is already at-end, so will do nothing.
Also, streaming all bytes in the zip file is slow, if you only want a small part of it.
Use a ZipFile
instead, since it allows random access to the zip entries, so it is faster, and it allows reading the entries in random order.
Note: The code below has been changed to use Java 7+ features for better error handling, such as try-with-resources and NIO.2.
ZipFile zipFile = new ZipFile(filePath);
extractFileFromZip(zipFile, path + "F1", "F1");
extractFileFromZip(zipFile, path + "F2", "F2");
public static boolean extractFileFromZip(ZipFile zipFile, String file, String name) throws IOException {
ZipEntry ze = zipFile.getEntry(name);
if (ze == null)
return false;
Path path = Paths.get(file);
Files.deleteIfExists(path);
try (InputStream in = zipFile.getInputStream(ze)) {
Files.copy(in, path);
}
return true;
}
Alternatively, stream it only once, then check for both names in the while
loop.
Map<String, String> nameMap = new HashMap<>();
nameMap.put("F1", path + "F1");
nameMap.put("F2", path + "F2");
extractFilesFromZip(filePath, nameMap);
public static void extractFilesFromZip(String filePath, Map<String, String> nameMap) throws IOException {
try (ZipInputStream zipIn = new ZipInputStream(new BufferedInputStream(new FileInputStream(filePath)))) {
for (ZipEntry ze; (ze = zipIn.getNextEntry()) != null; ) {
String file = nameMap.get(ze.getName());
if (file != null) {
Path path = Paths.get(file);
Files.deleteIfExists(path);
Files.copy(zipIn, path);
}
}
}
}
Upvotes: 1
Reputation: 310980
Because you read the entire stream to extract F1. So next time, for F2, getNextEntry()
returned null. You need to either reopen the zip stream, or, better still, pass a list of files to unzip to your method.
Upvotes: 0