Java 从 zip 文件中获取顶级文件夹
Java get the top level folder from zip file
我有点陷入这个问题。我只想打印 zip 文件中的顶级目录。例如,我有一个具有以下结构的 zip 文件:
Sample.zip
- sound
- game
-start.wav
-end.wav
- Intro
- custom
- Scene
- fight
- Angle
..............
上图显示:Sample.zip有2个文件夹(sound和custom),sound里面有2个文件夹game和Intro等等...
现在我知道如何从 zip 文件中打开和抓取目录了:例如(工作代码)
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);
}
现在我也知道我可以使用.getParent()
(如您在上面看到的)来获取顶级目录,但是上面的实现没有奏效。它会列出所有的目录,比如
null
sound
game
null
custom
scene
Angle
我的问题是如何才能真正只打印顶级文件夹,在上述情况下,sound
和 custom
?
如有任何提示,我将不胜感激。
你可以使用类似的东西:
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);
}
实际上我按照@JB Nizet 的建议进行了操作并得到了解决方法(它确实有效):
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);
}
上述解决方案有效,因为顶级目录没有父目录,因此返回 null 作为输出。所以我只是循环目录以查看它们是否有父目录,如果它们没有任何父目录则它们是顶级目录。
也许这段代码可以帮助您使用 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="";
下面的方法呢:
/**
* 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;
}
这是对我有用的方法。
我应该注意,我正在使用 StringUtils (Apache Lang3) 来计算多少次
“\”出现在 ZipEntry 路径中,但如果您不想使用 StringUtils,您可以
你自己的计数方法。
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;
}
该方法的用法:
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());
}
如果你想得到第一个文件夹之后的所有文件夹,
您可以通过将索引更改为您想要获取的文件夹的深度来实现。
在 Kotlin 中使用这个乐趣
fun getRootFolderName(fileAddress: String): String {
if (File(fileAddress).parent == null || ("" + File(fileAddress).parent).length < 1) return File(fileAddress).name
return getRootFolderName("" + File(fileAddress).parent)
}
我有点陷入这个问题。我只想打印 zip 文件中的顶级目录。例如,我有一个具有以下结构的 zip 文件:
Sample.zip
- sound
- game
-start.wav
-end.wav
- Intro
- custom
- Scene
- fight
- Angle
..............
上图显示:Sample.zip有2个文件夹(sound和custom),sound里面有2个文件夹game和Intro等等...
现在我知道如何从 zip 文件中打开和抓取目录了:例如(工作代码)
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);
}
现在我也知道我可以使用.getParent()
(如您在上面看到的)来获取顶级目录,但是上面的实现没有奏效。它会列出所有的目录,比如
null
sound
game
null
custom
scene
Angle
我的问题是如何才能真正只打印顶级文件夹,在上述情况下,sound
和 custom
?
如有任何提示,我将不胜感激。
你可以使用类似的东西:
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);
}
实际上我按照@JB Nizet 的建议进行了操作并得到了解决方法(它确实有效):
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);
}
上述解决方案有效,因为顶级目录没有父目录,因此返回 null 作为输出。所以我只是循环目录以查看它们是否有父目录,如果它们没有任何父目录则它们是顶级目录。
也许这段代码可以帮助您使用 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="";
下面的方法呢:
/**
* 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;
}
这是对我有用的方法。
我应该注意,我正在使用 StringUtils (Apache Lang3) 来计算多少次 “\”出现在 ZipEntry 路径中,但如果您不想使用 StringUtils,您可以 你自己的计数方法。
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;
}
该方法的用法:
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());
}
如果你想得到第一个文件夹之后的所有文件夹, 您可以通过将索引更改为您想要获取的文件夹的深度来实现。
在 Kotlin 中使用这个乐趣
fun getRootFolderName(fileAddress: String): String {
if (File(fileAddress).parent == null || ("" + File(fileAddress).parent).length < 1) return File(fileAddress).name
return getRootFolderName("" + File(fileAddress).parent)
}