Как архивировать файлы и папки в Java?

Пожалуйста, взгляните на приведенный ниже код.

public void startCompress(String path,String fileName,String outputLocation,int compressType,int filSize) throws Exception
    {        
        System.out.println("Input Location: "+path);
        System.out.println("Output Location: "+outputLocation);   

            System.out.println(compressType);
            byte[] bs=new byte[filSize];
            System.out.println(filSize);

            FileOutputStream fos=new FileOutputStream(outputLocation+"/test.zip");

            System.out.println(fos.toString());
            ZipOutputStream zos=new ZipOutputStream(fos);

            ZipEntry ze = new ZipEntry(fileName);

            zos.putNextEntry(ze);

            FileInputStream inputStream=new FileInputStream(path);

            int len;
            while((len=inputStream.read(bs))>0){
                zos.write(bs, 0, len);                
            }
            inputStream.close();
            zos.closeEntry();
            zos.close();

    }

В приведенном выше коде мы сжимаем файл, используя пакет java.util.zip. Но у нас есть проблема. То есть, если мы выбираем несколько файлов, то сжимается только один файл. Если мы выберем папку, сжатие просто не сработает.

Как я могу исправить это, чтобы сжать файл, файлы, папку, папки или даже вложенные папки? ZIP-пакет Java поддерживает форматы .zip, .tar, .tarGz и tarZ. Таким образом, решение не должно ограничиваться расширением .zip.


person JustCause    schedule 12.05.2015    source источник
comment
Затем передайте ему список файлов... что-то вроде это или это например   -  person MadProgrammer    schedule 12.05.2015
comment
mkyong.com/java/how-to-compress -files-in-zip-format А также stackoverflow.com/questions/15968883/   -  person Sercan Ozdemir    schedule 12.05.2015
comment
@SercanOzdemir: Его пример отличается, мы должны также определить, является ли выбранный файл или папка.   -  person JustCause    schedule 12.05.2015
comment
@MadProgrammer: Рад, что ты здесь. Можете ли вы помочь мне с примером кода?   -  person JustCause    schedule 12.05.2015
comment
@JustCause Взгляните на два связанных примера (обновленный комментарий)   -  person MadProgrammer    schedule 12.05.2015
comment
@MadProgrammer: Хорошо, я проверю.   -  person JustCause    schedule 12.05.2015
comment
@MadProgrammer: протестировал второй пример, но он создает папки для каждого отдельного файла внутри папки!   -  person JustCause    schedule 12.05.2015
comment
@JustCause Что ты имеешь в виду? Он создает папки для каждого файла в zip-файле или при его извлечении?   -  person MadProgrammer    schedule 12.05.2015
comment
@MadProgrammer: когда In извлек его, каждый файл внутри него имел папку. Я заархивировал папку с изображениями, каждое изображение было в своей папке, когда я его извлекал.   -  person JustCause    schedule 12.05.2015
comment
@JustCause Ура, я вернулся и посмотрел, и там была потенциальная ошибка, основанная на потребностях пользователя. Я исправил это, теперь файлы лучше сгруппированы в каталоги   -  person MadProgrammer    schedule 12.05.2015
comment
@MadProgrammer: Удивительно, спасибо. Я проверю. В любом случае, как сжать несколько файлов в один?   -  person JustCause    schedule 12.05.2015
comment
@MadProgrammer: Привет, он все еще создает папку для файлов.   -  person JustCause    schedule 12.05.2015
comment
@JustCause Да, это то, что он должен делать, иначе вы можете получить дубликаты zip-записей. Если вы не хотите сохранять информацию о пути, вы всегда комментируете раздел, который генерирует путь, и просто сохраняете имя файла в качестве имени записи.   -  person MadProgrammer    schedule 12.05.2015
comment
@MadProgrammer: нет. Я не это имел в виду. Представьте, что я выбрал папку с именем Folder. Теперь, после сжатия, когда я извлекаю его, несжатая версия должна содержать папку «Папка». Но вместо этого он содержит все внутри корневой папки, но не корневую папку.   -  person JustCause    schedule 12.05.2015
comment
Ах, так пример кода удаляет исходный путь. Вы должны иметь возможность изменить path = path.substring(sourcePath.length()); на что-то вроде path = path.substring(sourceFile.getParentFile().length());   -  person MadProgrammer    schedule 12.05.2015
comment
Если кто-то использует пример mkYong, строка FileInputStream in = new FileInputStream(SOURCE_FOLDER + File.separator + file); должна быть заменена на FileInputStream in = new FileInputStream(SOURCE_FOLDER + "/" + file);, поскольку окна \ недействительны для формата zip, невыполнение этого приведет к тому, что корневой каталог вне zip-файла будет и подчеркнут, например. _ - это была забавная отладка!   -  person JGlass    schedule 04.04.2019


Ответы (3)


Вот мое решение, в котором используется новый пакет java.nio. Просто вызовите zipDir, указав путь к каталогу. Он создаст zip-файл в том же месте, но с именем <directory>.zip.

private static Path buildPath(final Path root, final Path child) {
    if (root == null) {
        return child;
    } else {
        return Paths.get(root.toString(), child.toString());
    }
}

private static void addZipDir(final ZipOutputStream out, final Path root, final Path dir) throws IOException {
    try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir)) {
        for (Path child : stream) {
            Path entry = buildPath(root, child.getFileName());
            if (Files.isDirectory(child)) {
                addZipDir(out, entry, child);
            } else {
                out.putNextEntry(new ZipEntry(entry.toString()));
                Files.copy(child, out);
                out.closeEntry();
            }
        }
    }
}

public static void zipDir(final Path path) throws IOException {
    if (!Files.isDirectory(path)) {
        throw new IllegalArgumentException("Path must be a directory.");
    }

    BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(path.toString() + ".zip"));

    try (ZipOutputStream out = new ZipOutputStream(bos)) {
        addZipDir(out, path.getFileName(), path);
    }
}
person crowmagnumb    schedule 08.01.2016

Библиотеки zip для java нельзя использовать для сжатия папок более простым способом, например, сжать эту папку.

Вам нужно выполнить тест, если ввод является папкой или файлом самостоятельно. Если это файл - добавьте его в zip. Если это папка - переберите папку и добавьте каждый файл в zip. Для подпапок то же самое. Чтобы добавить в Zip более одного файла, вам нужно создать ZipEntry для каждого файла.

Вы можете попробовать этот код, который работает для меня:

public static void zip(File directory, File zipfile) throws IOException {
    URI base = directory.toURI();
    Deque<File> queue = new LinkedList<File>();
    queue.push(directory);
    OutputStream out = new FileOutputStream(zipfile);
    Closeable res = out;
    try {
        ZipOutputStream zout = new ZipOutputStream(out);
        res = zout;
        while (!queue.isEmpty()) {
            directory = queue.pop();
            for (File kid : directory.listFiles()) {
                String name = base.relativize(kid.toURI()).getPath();
                if (kid.isDirectory()) {
                    queue.push(kid);
                    name = name.endsWith("/") ? name : name + "/";
                    zout.putNextEntry(new ZipEntry(name));
                } else {
                    zout.putNextEntry(new ZipEntry(name));
                    copy(kid, zout);
                    zout.closeEntry();
                }
            }
        }
    } finally {
        res.close();
    }
}
person Veselin Davidov    schedule 12.05.2015

Обновлено из этого ответа, который исправляет проблему с каждым файл был добавлен в собственный каталог. Также лучше поддерживает проводник Windows.

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class Test {

    public static void main(String agrs[]) {
        ZipUtils appZip = new ZipUtils();
        appZip.zipIt(new File(source directory), new File(dest zip));
    }

    public static class ZipUtils {

        private final List<File> fileList;

        private List<String> paths;

        public ZipUtils() {
            fileList = new ArrayList<>();
            paths = new ArrayList<>(25);
        }

        public void zipIt(File sourceFile, File zipFile) {
            if (sourceFile.isDirectory()) {
                byte[] buffer = new byte[1024];
                FileOutputStream fos = null;
                ZipOutputStream zos = null;

                try {

                    // This ensures that the zipped files are placed
                    // into a folder, within the zip file
                    // which is the same as the one been zipped
                    String sourcePath = sourceFile.getParentFile().getPath();
                    generateFileList(sourceFile);

                    fos = new FileOutputStream(zipFile);
                    zos = new ZipOutputStream(fos);

                    System.out.println("Output to Zip : " + zipFile);
                    FileInputStream in = null;

                    for (File file : this.fileList) {
                        String path = file.getParent().trim();
                        path = path.substring(sourcePath.length());

                        if (path.startsWith(File.separator)) {
                            path = path.substring(1);
                        }

                        if (path.length() > 0) {
                            if (!paths.contains(path)) {
                                paths.add(path);
                                ZipEntry ze = new ZipEntry(path + "/");
                                zos.putNextEntry(ze);
                                zos.closeEntry();
                            }
                            path += "/";
                        }

                        String entryName = path + file.getName();
                        System.out.println("File Added : " + entryName);
                        ZipEntry ze = new ZipEntry(entryName);

                        zos.putNextEntry(ze);
                        try {
                            in = new FileInputStream(file);
                            int len;
                            while ((len = in.read(buffer)) > 0) {
                                zos.write(buffer, 0, len);
                            }
                        } finally {
                            in.close();
                        }
                    }

                    zos.closeEntry();
                    System.out.println("Folder successfully compressed");

                } catch (IOException ex) {
                    ex.printStackTrace();
                } finally {
                    try {
                        zos.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }

        protected void generateFileList(File node) {

// add file only
            if (node.isFile()) {
                fileList.add(node);

            }

            if (node.isDirectory()) {
                File[] subNote = node.listFiles();
                for (File filename : subNote) {
                    generateFileList(filename);
                }
            }
        }
    }

}
person MadProgrammer    schedule 12.05.2015