Java. Как архивировать только определенные файлы из папки в один архив

278
17 апреля 2017, 03:48

Всем привет. Может вопрос банальный, но в Java я новичок и никак не могу додуматься.

Проблема такая:

Есть папка, в ней много разных файлов. Я отбираю только нужные мне (по дате изменения). Использую java.util.zip.ZipOutputStream. А когда передаю файл в метод архивации, он делает мне отдельный архив для каждого файла. Есть какие-то способы, которые позволят сделать единый архив, без копирования/перемещения нужных файлов в отдельную папку?

Код, в котором из массива файлов выбираю нужные и передаю на архивацию:

for (File s : files) {
            BasicFileAttributes attr = Files.readAttributes(s.toPath(), BasicFileAttributes.class);
            if (dateChecker(attr.lastModifiedTime())) {                            
                ZipOutputStream out = new ZipOutputStream(new FileOutputStream(s.getPath() + ".zip"));
                doZip(s, out);
                out.close();
            }
        }

Метод архивации:

 void doZip(File dir, ZipOutputStream out){
    try {
        out.setLevel(9);
        out.putNextEntry(new ZipEntry(dir.getName()));
        write(new FileInputStream(dir), out);
    }
    catch (IOException e) {
        e.printStackTrace();
    }
}
private static void write(InputStream in, OutputStream out) throws IOException {
    byte[] buffer = new byte[1024];
    int len;
    while ((len = in.read(buffer)) >= 0)
        out.write(buffer, 0, len);
    in.close();
}
Answer 1

В действительности вы делаете несколько архивов своими руками.

for (File s : files) {    
    BasicFileAttributes attr = Files.readAttributes(s.toPath(), BasicFileAttributes.class);
    if (dateChecker(attr.lastModifiedTime())) {                            
        ZipOutputStream out = new ZipOutputStream(new FileOutputStream(s.getPath() + ".zip"));
        doZip(s, out);
        out.close();
    }
}

Здесь вы создаете для каждого следующего файла новый стрим (в цикле), а то есть и файл с новым названием, соответствующим <имя файла>.zip. И после архивации закрываете его, то есть создаете в файловой системе файл архива для конкретного файла.

Вам нужно создать один ZipOutputStream на всю обработку и при переборе файлов сохранять их в него. Это будет выглядеть примерно так:

List<File> filesToArchive = new LinkedList<>();
for (File file : files) {
    BasicFileAttributes attr = Files.readAttributes(file.toPath(), BasicFileAttributes.class);
    if (dateChecker(attr.lastModifiedTime())) {
        filesToArchive.add(file);
    }
}
doZip(filesToArchive, <resultname>.zip);

И в этом случае doZip преобразуется в вариант наподобии:

private static void doZip(List<File> files, String archiveName){
    try {
        ZipOutputStream out = new ZipOutputStream(new FileOutputStream(archiveName));
        out.setLevel(9);
        for (File file : files) {
            out.putNextEntry(new ZipEntry(file.getName()));
            write(new FileInputStream(dir), out);
        }
        out.close();
    }
    catch (IOException e) {
        e.printStackTrace();
    }
}
READ ALSO
Теряется сессия при вызове сервлета

Теряется сессия при вызове сервлета

Прохожу авторизацию через JDBCRealm/j_security_checkСоздается сессия, на странице вызываю request

213
WhatsApp web в android WebView

WhatsApp web в android WebView

Какой user-agent нужно использовать для отображения webwhatsapp

291
использование 2-x asynctaskloader

использование 2-x asynctaskloader

Использую в фрагменте загрузчик который возвращает данные с Api, хочу еще добавить реализацию одного загрузчика который будет возвращать...

202
this при объявлении конструктора Java

this при объявлении конструктора Java

Есть два варианта объявления конструктора:

231