Reputation: 593
I kind of stuck in this problem. I want to print only the top level directory from a zip file. For example I have a zip file with following structure:
Sample.zip
- sound
- game
-start.wav
-end.wav
- Intro
- custom
- Scene
- fight
- Angle
..............
Above figure shows: the Sample.zip has 2 folders (sound and custom), and inside sound there are 2 folders game and Intro and so on...
Now I know how to open and grab the directory from zip file: For example (working code)
try {
appFile = ("../../Sample.zip"); // just the path to zip file
ZipFile zipFile = new ZipFile(appFile);
Enumeration<? extends ZipEntry> entries = zipFile.entries();
while (entries.hasMoreElements()) {
ZipEntry entry = entries.nextElement();
if(entry.isDirectory()){
String dir = entry.getName();
File file = new File(dir);
System.out.println(file.getParent());
}
}
} catch (IOException e) {
System.out.println("Error opening Zip" +e);
}
Now I also know I can use .getParent()
(as you see above) to get the top level dir, but the above implementation has not worked. It'll list out all the directory , like
null
sound
game
null
custom
scene
Angle
My question is how can I actually print only the top level folders, In above scenario , sound
and custom
?
For any sort of hint, I'll be thankful.
Upvotes: 3
Views: 7873
Reputation: 54
This is the method that worked for me.
I should note that I am using StringUtils (Apache Lang3) to count how many times "\" appears in the ZipEntry path, although if you don't want to use StringUtils you could make your own method for counting.
public static ArrayList<ZipEntry> getZipContent(File file, int index) {
try {
ArrayList<String> innerFoldersPaths = new ArrayList<String>();
ArrayList<ZipEntry> retEntries = new ArrayList<ZipEntry>();
ZipFile zipFile = new ZipFile(file);
Enumeration<? extends ZipEntry> entries = zipFile.entries();
while (entries.hasMoreElements()) {
ZipEntry entry = entries.nextElement();
// If you also want to get files remove the "if (entry.isDirectory())" statement.
if (entry.isDirectory()) {
String backSlashName = entry.getName().replace("/", "\\"); // Important to do this.
if (StringUtils.countMatches(backSlashName, "\\") > index - 1) { // Using Apache StringUtils
String folder[] = backSlashName.split(Pattern.quote("\\"));
String finalFolder = "";
// Getting the folders path inside the .zip file .
for (int i = 0; i < index; i++) {
folder[i] = folder[i] + "\\";
finalFolder = finalFolder + folder[i];
}
finalFolder = finalFolder.replace("\\", "/"); // Important to do this.
if (innerFoldersPaths.contains(finalFolder)) {
} else {
innerFoldersPaths.add(finalFolder);
}
}
}
}
for (String backSlashName : innerFoldersPaths) {
retEntries.add(zipFile.getEntry(backSlashName));
}
zipFile.close();
return retEntries;
} catch (Exception exception) {
// handle the exception in the way you want.
exception.printStackTrace();
}
return null;
}
The usage of this method:
File file = new File("Your zip file here");
for (ZipEntry zipEntry : getZipContent(file, 1)) { // This would return all the folders in the first file
// Do what ever your wantt with the ZipEntry
System.out.println(zipEntry.getName());
}
If you want to get all the folders past the first one, you could do it by changing the index to how deep the folders that you want to get are.
Upvotes: 0
Reputation: 1971
What about following method:
/**
* Get the root folders within a zip file
*
* @param zipFile the zip file to be used. E.g. '/home/foo/bar.zip'
* @return a list containing all root folders
* @throws Exception if case the zip file cannot be found or read.
*/
public static List<String> getGetRootDirectoriesWithinZip(String zipFile) throws Exception {
Set<String> set = new LinkedHashSet();
//get the zip file content stream
ZipInputStream zipInputStream = new ZipInputStream(new FileInputStream(zipFile));
//get the zipped file set entry
ZipEntry zipEntry = zipInputStream.getNextEntry();
while (zipEntry != null) {
String fileName = zipEntry.getName();
Path path = Paths.get(fileName);
int nameCount = path.getNameCount();
for (int i = 0; i < nameCount; i++) {
if (path != null && path.getParent() != null) {
path = path.getParent();
}
}
set.add(path.toString());
zipEntry = zipInputStream.getNextEntry();
}
List<String> retList = new ArrayList<>();
retList.addAll(set);
return retList;
}
Upvotes: 1
Reputation: 1174
Maybe this code will help you with using InputStream
String topFolder="";
String topFolder2="";
Boolean hasTopFolder=true;
try{
File dir = new File(path+"/html5"+catalogue.getIdProduit());
if (!dir.exists()) {
dir.mkdirs();
}
String outputFolder= "path/to/outputFolder";
InputStream input = file.getInputstream();
//get the zip file content
ZipInputStream zis = new ZipInputStream(input);
//get the zipped file list entry
ZipEntry ze = zis.getNextEntry();
while(ze!=null){
if (ze.isDirectory()) {
System.out.println("is directory : "+ ze.getName());
if ("".equals(topFolder)){
topFolder = ze.getName().split("/")[0];
System.out.println("is directory topFolder : "+ ze.getName());
}
if (("".equals(topFolder2)) && (!topFolder.equals(ze.getName().split("/")[0]))){
hasTopFolder=false;
topFolder2=ze.getName().split("/")[0];
System.out.println("is directory topFolder2 : "+ ze.getName());
}
ze = zis.getNextEntry();
continue;
}
String fileName = ze.getName();
File newFile = new File(outputFolder + File.separator + fileName);
System.out.println("file unzip : "+ newFile.getAbsoluteFile());
//create all non exists folders
//else you will hit FileNotFoundException for compressed folder
new File(newFile.getParent()).mkdirs();
FileOutputStream fos = new FileOutputStream(newFile);
int len;
while ((len = zis.read(buffer)) > 0) {
fos.write(buffer, 0, len);
}
fos.close();
ze = zis.getNextEntry();
}
zis.closeEntry();
zis.close();
System.out.println("Done");
}
catch(IOException e){
e.printStackTrace();
}
if (hasTopFolder){
topFolder="/"+topFolder;
}
else
topFolder="";
Upvotes: 1
Reputation: 593
Actually I did following as suggested by @JB Nizet and get a work around(it actually work ):
try {
appFile = ("../../Sample.zip"); // just the path to zip file
ZipFile zipFile = new ZipFile(appFile);
Enumeration<? extends ZipEntry> entries = zipFile.entries();
while (entries.hasMoreElements()) {
ZipEntry entry = entries.nextElement();
if(entry.isDirectory()){
File file = new File(entry.getName());
if(file.getParent() == null){
System.out.println(file.getName());
}
}
}
} catch (IOException e) {
System.out.println("Error opening Zip" +e);
}
The above solution has worked because the top level dir has no parent and therefore returned null as output. So I just loop around the directories to see if they have parents, if they dont have any parent then they are top level directory.
Upvotes: 3
Reputation: 51
You can use something like that:
try{
String appFile = "../file.zip"; // just the path to zip file
ZipFile zipFile = new ZipFile(appFile);
Enumeration<? extends ZipEntry> entries = zipFile.entries();
while (entries.hasMoreElements()) {
ZipEntry entry = entries.nextElement();
if(entry.isDirectory() && !entry.getName().matches("\\S+/\\S+")){ //it's a top level folder
System.out.println(entry.getName());
}
}
} catch (IOException e) {
System.out.println("Error opening Zip" +e);
}
Upvotes: 2