ZipOutputStream 不会为目录创建新条目
ZipOutputStream does not create new entries for Directories
我正在尝试在 .zip 文件中创建目录,但在 .zip 中只创建了一个目录。我不确定为什么只创建第一个目录。每次有目录时都会调用 zip() 方法。
列出文件的方法:
private Set<String> listFiles(String path){
File f = new File(path);
Set<String> files = new HashSet<>();
for(File file : Objects.requireNonNull(f.listFiles())){
files.add(file.getPath());
}
return files;
}
压缩方法:
private void zip(Set<String> path){
try {
BufferedInputStream bufferedInputStream = null;
BufferedOutputStream bufferedOutputStream;
ZipOutputStream zipOutputStream;
File f;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
bufferedOutputStream = new BufferedOutputStream(new FileOutputStream("/sdcard/Android/data/com.kpwnapps.pmmpplugins/files/PocketMine-MP/test.zip"));
zipOutputStream= new ZipOutputStream(bufferedOutputStream, StandardCharsets.UTF_8);
for (String file : path){
f = new File(file);
if (f.isDirectory()){
zipOutputStream.putNextEntry(new ZipEntry(f.getName() + "/"));
zip(listFiles(f.getPath()));
}else {
bufferedInputStream = new BufferedInputStream(new FileInputStream(file));
zipOutputStream.putNextEntry(new ZipEntry(f.getName()));
IOUtils.copy(bufferedInputStream, zipOutputStream);
zipOutputStream.closeEntry();
}
*/
}
if (bufferedInputStream != null){
bufferedInputStream.close();
}
zipOutputStream.flush();
zipOutputStream.close();
}
}catch (Exception ignored){
}
}
我有点惊讶这竟然能奏效。
当您的 zip()
方法递归调用自身时,它会创建一个新的 FileOutputStream
,其文件名与上一次调用相同。这意味着您的递归调用相互叠加而不是附加到单个 zip 文件。
您应该只打开 FileOutputStream / ZipOutputStream 一次,然后使用它来压缩所有文件和目录。
这意味着重写一些代码,以便在压缩的第一级创建 zipOutputStream
,然后调用内部方法 zip(path, zipOutputStream)
。递归调用也必须调用此 zip(path, zipOutputStream)
方法。
这看起来像
private void zip(Set<String> path) {
// create FileOutputStream, ZipOutputStream
ZipOutputStream zipOutputStream = new ZipOutputStream(fileOutputStream);
// call worker method
zip(path, zipOutputStream);
// close output stream
zipOutputStream.flush();
zipOutputStream.close();
}
private void zip(Set<String> path, ZipOutputStream zipOutputStream) {
// loop over paths
if (f.isDirectory()) {
zipOutputStream.putNextEntry(new ZipEntry(f.getName() + "/"));
zip(listFiles(f.getPath()), zipOutputStream);
}
// end of loop over paths
}
我正在尝试在 .zip 文件中创建目录,但在 .zip 中只创建了一个目录。我不确定为什么只创建第一个目录。每次有目录时都会调用 zip() 方法。
列出文件的方法:
private Set<String> listFiles(String path){
File f = new File(path);
Set<String> files = new HashSet<>();
for(File file : Objects.requireNonNull(f.listFiles())){
files.add(file.getPath());
}
return files;
}
压缩方法:
private void zip(Set<String> path){
try {
BufferedInputStream bufferedInputStream = null;
BufferedOutputStream bufferedOutputStream;
ZipOutputStream zipOutputStream;
File f;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
bufferedOutputStream = new BufferedOutputStream(new FileOutputStream("/sdcard/Android/data/com.kpwnapps.pmmpplugins/files/PocketMine-MP/test.zip"));
zipOutputStream= new ZipOutputStream(bufferedOutputStream, StandardCharsets.UTF_8);
for (String file : path){
f = new File(file);
if (f.isDirectory()){
zipOutputStream.putNextEntry(new ZipEntry(f.getName() + "/"));
zip(listFiles(f.getPath()));
}else {
bufferedInputStream = new BufferedInputStream(new FileInputStream(file));
zipOutputStream.putNextEntry(new ZipEntry(f.getName()));
IOUtils.copy(bufferedInputStream, zipOutputStream);
zipOutputStream.closeEntry();
}
*/
}
if (bufferedInputStream != null){
bufferedInputStream.close();
}
zipOutputStream.flush();
zipOutputStream.close();
}
}catch (Exception ignored){
}
}
我有点惊讶这竟然能奏效。
当您的 zip()
方法递归调用自身时,它会创建一个新的 FileOutputStream
,其文件名与上一次调用相同。这意味着您的递归调用相互叠加而不是附加到单个 zip 文件。
您应该只打开 FileOutputStream / ZipOutputStream 一次,然后使用它来压缩所有文件和目录。
这意味着重写一些代码,以便在压缩的第一级创建 zipOutputStream
,然后调用内部方法 zip(path, zipOutputStream)
。递归调用也必须调用此 zip(path, zipOutputStream)
方法。
这看起来像
private void zip(Set<String> path) {
// create FileOutputStream, ZipOutputStream
ZipOutputStream zipOutputStream = new ZipOutputStream(fileOutputStream);
// call worker method
zip(path, zipOutputStream);
// close output stream
zipOutputStream.flush();
zipOutputStream.close();
}
private void zip(Set<String> path, ZipOutputStream zipOutputStream) {
// loop over paths
if (f.isDirectory()) {
zipOutputStream.putNextEntry(new ZipEntry(f.getName() + "/"));
zip(listFiles(f.getPath()), zipOutputStream);
}
// end of loop over paths
}