Прикрепил код готового решения. Что здесь на самом деле происходит? Как я понял, то новый архив не создаётся, а просто в старый добавляется файл и то ли перезаписывается старые, то ли дублируются. Объясните пожалуйста
public class Solution {
public static void main(String[] args) throws IOException {
List<Content> entries = getContents(args[1]);
FileOutputStream zipFile = new FileOutputStream(args[1]);
ZipOutputStream zip = new ZipOutputStream(zipFile);
//кладем в него ZipEntry –«архивный объект»
File file = new File(args[0]);
zip.putNextEntry(new ZipEntry("new/" + file.getName()));
//копируем файл «document-for-archive.txt» в архив под именем «document.txt»
Files.copy(file.toPath(), zip);
//копируем все остальные файлы
for (Content content : entries) {
if (!content.getFileName().equals("new/" + file.getName())) content.saveToZip(zip);
}
// закрываем архив
zip.close();
}
private static List<Content> getContents(String arg) throws IOException {
List<Content> entries = new ArrayList<>();
try (ZipInputStream zipInputStream = new ZipInputStream(new FileInputStream(arg))) {
ZipEntry currentEntry;
byte[] buffer = new byte[1024];
while ((currentEntry = zipInputStream.getNextEntry()) != null) {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
int length = 0;
while ((length = zipInputStream.read(buffer)) > 0) {
outputStream.write(buffer, 0, length);
}
entries.add(new Content(currentEntry.getName(), outputStream.toByteArray()));
}
}
return entries;
}
static class Content {
String fileName;
byte[] body;
Content(String fileName, byte[] body) {
this.fileName = fileName;
this.body = body;
}
public String getFileName() {
return fileName;
}
void saveToZip(ZipOutputStream zip) throws IOException {
ZipEntry zipEntry = new ZipEntry(fileName);
zip.putNextEntry(zipEntry);
zip.write(body);
zip.closeEntry();
}
}
}
Ростислав
34 уровень
Не совсем понял с архивом
Решен
args[1]), добавляя в него новый файл (args[0]) под именемnew/имя_файла, а также переписывает все старые файлы, кроме файла с таким же именем, чтобы избежать дублирования. 🔍 Подробный разбор кода 1. Чтение текущего содержимого ZIP-архива МетодgetContents(...)открывает архив по путиargs[1], читает всеZipEntry, сохраняет имя файла и его содержимое в списокContent. То есть, вся структура архива загружается в память. 2. Открытие выходного ZIP-архива Тут важно: 📌new FileOutputStream(...)с именем того же файла, что и существующий архив перезаписывает его начисто. То есть, архив очищается и создаётся заново — новый, пустой ZIP-файл. 3. Добавление нового файла Создаётся новыйZipEntryс путёмnew/имя_файла, и туда записывается содержимое указанного файла.fileNameравный"new/" + имя_файла. Это делается, чтобы не продублировать файл, если он уже был в архиве. 5. Закрытие архива ✅ Что происходит в итоге- Файл-архив полностью пересоздаётся.
- В него добавляется новый файл под путём
- Все старые файлы из архива добавляются обратно, кроме того, который потенциально конфликтует по имени.
- Дубликатов не возникает, потому что файл с тем же путём не сохраняется повторно.
❗ Важное замечание Если ты думал, что в архив «что-то добавляется поверх», — это не так. Архив сначала читается, затем удаляется/перезаписывается, и создаётся заново со старым содержимым и новым файлом. Это может быть неэффективно для больших архивов, потому что всё содержимое архив читается и пересоздаётся. 💡 Альтернативы Если бы нужно было добавить файл в архив без полного пересоздания, можно было бы использовать библиотеки вродеnew/имя_файла.Zip4j, которые поддерживают update ZIP-файлов без полной перезаписи. Но стандартныйjava.util.zipэтого не позволяет. Если хочешь, могу переписать этот код в более чистом и понятном виде или предложить вариант сZip4j.