在Java中压缩文件时如何保留文件夹结构?

4
我想压缩一个文件夹,其结构如下:
temp/folder1/file1
temp/folder2/file2
temp/file3
并且要保持完全相同的目录结构。目前,当我压缩它时,我得到的压缩文件不保持目录结构。它看起来像这样:
file1
file2
file3
我该怎么做才能像所有常规的压缩应用程序一样将文件添加到它们各自的文件夹中?
这是我目前拥有的代码:
package com.damastah.deflash;

import android.util.Log;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class Compress {
    private static final int BUFFER = 2048;

    private ArrayList<File> _files;
    private String _zipFile;

    public Compress(ArrayList<File> files, String zipFile) {
        _files = files;
        _zipFile = zipFile;
    }

    public void zip() {
        try {
            BufferedInputStream origin = null;
            FileOutputStream dest = new FileOutputStream(_zipFile);

            ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(
                    dest));

            byte data[] = new byte[BUFFER];
            Log.e("Compress - zip", "test");
            for (int i = 0; i < _files.size(); i++) {
                Log.v("Compress", "Adding: " + _files.get(i).getAbsolutePath());
                FileInputStream fi = new FileInputStream(_files.get(i)
                        .getAbsolutePath());
                origin = new BufferedInputStream(fi, BUFFER);
                ZipEntry entry;
                if (_files.get(i).getAbsolutePath().contains("."))
                    entry = new ZipEntry(_files
                            .get(i)
                            .getAbsolutePath()
                            .substring(
                                    _files.get(i).getAbsolutePath()
                                            .lastIndexOf("/") + 1));
                else
                    entry = new ZipEntry(_files.get(i).getAbsolutePath());
                out.putNextEntry(entry);

                int count;
                while ((count = origin.read(data, 0, BUFFER)) != -1) {
                    out.write(data, 0, count);
                }

                origin.close();
            }

            out.close();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}
1个回答

1

我不是安卓开发者,所以请把这段代码仅作为提示。

class ZipCompress {
    public static void main(String[] args) throws IOException {

        String dir = "d:\\My folder\\";
        // this entries I want to put in archives in the way they are now
        String[] entries = { "temp\\folder1\\file1.txt", "temp\\folder2\\file2.txt",
                "temp\\file3.txt" };

        ZipOutputStream zipos = new ZipOutputStream(new BufferedOutputStream(
                new FileOutputStream(dir + "archive.zip")));

        // time to create entries and fill them with data
        for (String entrie : entries) {
            System.out.println("Writing file: " + dir + entrie);

            // prepering file stream
            BufferedInputStream fileStream = new BufferedInputStream(
                    new FileInputStream(dir + entrie));

//--------------------------------------------------------------------------
//          Here we decide how we entry will look like in archive.
//          We use only part of path from String[] entries
//          like "temp\\folder1\\file1.txt"
//--------------------------------------------------------------------------
            ZipEntry newEntry = new ZipEntry(entrie);

            newEntry.setComment("comment to entry: " + newEntry);

            // now lets put this entry in archive
            zipos.putNextEntry(newEntry);

            // lets put data from file to current archive entry
            int c;
            while ((c = fileStream.read()) != -1)
                zipos.write(c);
            fileStream.close();
        }
        zipos.close();
    }
}

编辑

我不确定你想在这里做什么

if (_files.get(i).getAbsolutePath().contains("."))
                    entry = new ZipEntry(_files
                            .get(i)
                            .getAbsolutePath()
                            .substring(
                                    _files.get(i).getAbsolutePath()
                                            .lastIndexOf("/") + 1));

从我看到的,它会删除文件路径,只留下文件名(类似于_files.get(i).getName())。如果是这样,那就是为什么你的zip文件中没有文件夹结构的原因。你说zip条目应该只是那个文件名,没有任何文件夹。

所以,如果你想让zip文件包含/my/full/path/to/folder/temp/folder1/file1路径的一部分,比如temp/folder1/file1,只需在创建ZipEntry时删除该路径的不必要部分即可。

String dir = "/my/full/path/to/folder/";
for (int i = 0; i < _files.size(); i++) {
...
    if (_files.get(i).getAbsolutePath().contains(".")) {
        entry = new ZipEntry(_files
            .get(i).getAbsolutePath().replace(dir, ""));
...

为了指定文件路径,您应该使用嵌套的File构造函数或File.separator,而不是字面上的反斜杠,以保持代码的可移植性。 - millimoose
对于阅读答案的人而言,这更像是一个技巧建议,而不是真正的更正。使用文本字面值可以使代码示例更易于阅读且无需辅助函数。 - millimoose
那么现有的代码没有一两行就可以解决的问题,是吗?我只是在这里看答案,并没有看到处理存档中文件夹的代码行。 - Damastah
1
@Damastah,我不确定你为什么有这个文件夹。也许条目不能以“/”标记开头,而zip认为有一些空命名的文件夹(这只是一个猜测)。因此,请尝试从条目中删除第一个“/”,例如将“/folder/whatever”更改为“folder/whatever”,然后告诉我是否有所帮助。 - Pshemo
1
@Damastah,我很高兴能帮到你。也许不是因为条目不能以“/”开头,而是因为在许多操作系统中,“/”是根目录,所以我的上一条评论真的很幸运 :) - Pshemo
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接