Как создать zip-файл на Java
У меня есть динамический текстовый файл, который выбирает содержимое из базы данных в соответствии с запросом пользователя. Я должен записать этот контент в текстовый файл и заархивировать его в папку в сервлете. Как мне это сделать?
9 ответов:
рассмотрим пример:
StringBuilder sb = new StringBuilder(); sb.append("Test String"); File f = new File("d:\test.zip"); ZipOutputStream out = new ZipOutputStream(new FileOutputStream(f)); ZipEntry e = new ZipEntry("mytext.txt"); out.putNextEntry(e); byte[] data = sb.toString().getBytes(); out.write(data, 0, data.length); out.closeEntry(); out.close();
это создаст Zip-файл, расположенный в корне D: с именем 'test.zip', который будет содержать один файл под названием " mytext.txt'. Конечно, вы можете добавить больше записей zip, а также указать подкаталог, например:
ZipEntry e = new ZipEntry("folderName/mytext.txt");
вы можете найти дополнительную информацию о сжатии с java здесь:
http://www.oracle.com/technetwork/articles/java/compress-1565076.html
Java 7 имеет встроенную систему ZipFileSystem, которая может использоваться для создания, записи и чтения файла из zip-файла.
Java Doc: Поставщик ZipFileSystem
Map<String, String> env = new HashMap<>(); env.put("create", "true"); URI uri = URI.create("jar:file:/codeSamples/zipfs/zipfstest.zip"); try (FileSystem zipfs = FileSystems.newFileSystem(uri, env)) { Path externalTxtFile = Paths.get("/codeSamples/zipfs/SomeTextFile.txt"); Path pathInZipfile = zipfs.getPath("/SomeTextFile.txt"); // copy a file into the zip file Files.copy(externalTxtFile, pathInZipfile, StandardCopyOption.REPLACE_EXISTING); }
для записи ZIP-файла используется ZipOutputStream. Для каждой записи, которую вы хотите поместить в ZIP-файл, вы создаете объект ZipEntry. Вы передаете имя файла конструктору ZipEntry; он устанавливает другие параметры, такие как дата файла и метод распаковки. Вы можете переопределить эти параметры, если хотите. Затем вы вызываете метод putNextEntry в ZipOutputStream, чтобы начать писать новый файл. Отправьте данные файла в ZIP-поток. Когда вы закончите, позвоните closeEntry. Повторите для всех файлы, которые вы хотите сохранить. Вот скелет кода:
FileOutputStream fout = new FileOutputStream("test.zip"); ZipOutputStream zout = new ZipOutputStream(fout); for all files { ZipEntry ze = new ZipEntry(filename); zout.putNextEntry(ze); send data to zout; zout.closeEntry(); } zout.close();
вот пример кода для сжатия весь каталог(включая sub-файлы и подкаталоги), он использует функцию дерева файлов walk Java NIO.
import java.io.FileOutputStream; import java.io.IOException; import java.nio.file.*; import java.nio.file.attribute.BasicFileAttributes; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; public class ZipCompress { public static void compress(String dirPath) { Path sourceDir = Paths.get(dirPath); String zipFileName = dirPath.concat(".zip"); try { ZipOutputStream outputStream = new ZipOutputStream(new FileOutputStream(zipFileName)); Files.walkFileTree(sourceDir, new SimpleFileVisitor<Path>() { @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) { try { Path targetFile = sourceDir.relativize(file); outputStream.putNextEntry(new ZipEntry(targetFile.toString())); byte[] bytes = Files.readAllBytes(file); outputStream.write(bytes, 0, bytes.length); outputStream.closeEntry(); } catch (IOException e) { e.printStackTrace(); } return FileVisitResult.CONTINUE; } }); outputStream.close(); } catch (IOException e) { e.printStackTrace(); } } }
чтобы использовать это, просто позвоните
ZipCompress.compress("target/directoryToCompress");
и вы получите zip - файл directoryToCompress.молнии
public static void main(String args[]) { omtZip("res/", "omt.zip"); } public static void omtZip(String path,String outputFile) { final int BUFFER = 2048; boolean isEntry = false; ArrayList<String> directoryList = new ArrayList<String>(); File f = new File(path); if(f.exists()) { try { FileOutputStream fos = new FileOutputStream(outputFile); ZipOutputStream zos = new ZipOutputStream(new BufferedOutputStream(fos)); byte data[] = new byte[BUFFER]; if(f.isDirectory()) { //This is Directory do{ String directoryName = ""; if(directoryList.size() > 0) { directoryName = directoryList.get(0); System.out.println("Directory Name At 0 :"+directoryName); } String fullPath = path+directoryName; File fileList = null; if(directoryList.size() == 0) { //Main path (Root Directory) fileList = f; }else { //Child Directory fileList = new File(fullPath); } String[] filesName = fileList.list(); int totalFiles = filesName.length; for(int i = 0 ; i < totalFiles ; i++) { String name = filesName[i]; File filesOrDir = new File(fullPath+name); if(filesOrDir.isDirectory()) { System.out.println("New Directory Entry :"+directoryName+name+"/"); ZipEntry entry = new ZipEntry(directoryName+name+"/"); zos.putNextEntry(entry); isEntry = true; directoryList.add(directoryName+name+"/"); }else { System.out.println("New File Entry :"+directoryName+name); ZipEntry entry = new ZipEntry(directoryName+name); zos.putNextEntry(entry); isEntry = true; FileInputStream fileInputStream = new FileInputStream(filesOrDir); BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream, BUFFER); int size = -1; while( (size = bufferedInputStream.read(data, 0, BUFFER)) != -1 ) { zos.write(data, 0, size); } bufferedInputStream.close(); } } if(directoryList.size() > 0 && directoryName.trim().length() > 0) { System.out.println("Directory removed :"+directoryName); directoryList.remove(0); } }while(directoryList.size() > 0); }else { //This is File //Zip this file System.out.println("Zip this file :"+f.getPath()); FileInputStream fis = new FileInputStream(f); BufferedInputStream bis = new BufferedInputStream(fis,BUFFER); ZipEntry entry = new ZipEntry(f.getName()); zos.putNextEntry(entry); isEntry = true; int size = -1 ; while(( size = bis.read(data,0,BUFFER)) != -1) { zos.write(data, 0, size); } } //CHECK IS THERE ANY ENTRY IN ZIP ? ----START if(isEntry) { zos.close(); }else { zos = null; System.out.println("No Entry Found in Zip"); } //CHECK IS THERE ANY ENTRY IN ZIP ? ----START }catch(Exception e) { e.printStackTrace(); } }else { System.out.println("File or Directory not found"); } } }
Zip4j использует полностью java-код без какой-либо поддержки собственного кода, и это то, что делает его лучше подходит для меня. Zip4j предоставляет следующие возможности:
- создание, добавление, извлечение, обновление, удаление файлов из Zip-файла
- чтение / запись защищенных паролем Zip-файлов
- поддерживает шифрование AES 128/256
- Поддерживает Стандартное Шифрование Zip
- поддерживает формат Zip64
- Магазин Поддержек (Отсутствие Обжатия) и выкачать метод сжатия
- создание или извлечение файлов из разделенных Zip-файлов (например: z01, z02,...zip)
- поддерживает имена файлов Unicode
- Мониторинг Прогресса
CreatePasswordProtectedZipExample.java
import java.io.File; import java.util.ArrayList; import net.lingala.zip4j.core.ZipFile; import net.lingala.zip4j.exception.ZipException; import net.lingala.zip4j.model.ZipParameters; import net.lingala.zip4j.util.Zip4jConstants; public class CreatePasswordProtectedZipExample { public static void main(String[] args) { try { //This is name and path of zip file to be created ZipFile zipFile = new ZipFile("C:/temp/test.zip"); //Add files to be archived into zip file ArrayList<File> filesToAdd = new ArrayList<File>(); filesToAdd.add(new File("C:/temp/test1.txt")); filesToAdd.add(new File("C:/temp/test2.txt")); //Initiate Zip Parameters which define various properties ZipParameters parameters = new ZipParameters(); parameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE); // set compression method to deflate compression //DEFLATE_LEVEL_FASTEST - Lowest compression level but higher speed of compression //DEFLATE_LEVEL_FAST - Low compression level but higher speed of compression //DEFLATE_LEVEL_NORMAL - Optimal balance between compression level/speed //DEFLATE_LEVEL_MAXIMUM - High compression level with a compromise of speed //DEFLATE_LEVEL_ULTRA - Highest compression level but low speed parameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL); //Set the encryption flag to true parameters.setEncryptFiles(true); //Set the encryption method to AES Zip Encryption parameters.setEncryptionMethod(Zip4jConstants.ENC_METHOD_AES); //AES_STRENGTH_128 - For both encryption and decryption //AES_STRENGTH_192 - For decryption only //AES_STRENGTH_256 - For both encryption and decryption //Key strength 192 cannot be used for encryption. But if a zip file already has a //file encrypted with key strength of 192, then Zip4j can decrypt this file parameters.setAesKeyStrength(Zip4jConstants.AES_STRENGTH_256); //Set password parameters.setPassword("howtodoinjava"); //Now add files to the zip file zipFile.addFiles(filesToAdd, parameters); } catch (ZipException e) { e.printStackTrace(); } } }
Spring Boot controller, zip файлы в каталоге, и могут быть загружены.
@RequestMapping(value = "/files.zip") @ResponseBody byte[] filesZip() throws IOException { File dir = new File("./"); File[] filesArray = dir.listFiles(); if (filesArray == null || filesArray.length == 0) System.out.println(dir.getAbsolutePath() + " have no file!"); ByteArrayOutputStream bo = new ByteArrayOutputStream(); ZipOutputStream zipOut= new ZipOutputStream(bo); for(File xlsFile:filesArray){ if(!xlsFile.isFile())continue; ZipEntry zipEntry = new ZipEntry(xlsFile.getName()); zipOut.putNextEntry(zipEntry); zipOut.write(IOUtils.toByteArray(new FileInputStream(xlsFile))); zipOut.closeEntry(); } zipOut.close(); return bo.toByteArray(); }
Если вы хотите распаковать без программного обеспечения лучше использовать этот код. Другой код с pdf файлами отправляет ошибку на ручную распаковку
byte[] buffer = new byte[1024]; try { FileOutputStream fos = new FileOutputStream("123.zip"); ZipOutputStream zos = new ZipOutputStream(fos); ZipEntry ze= new ZipEntry("file.pdf"); zos.putNextEntry(ze); FileInputStream in = new FileInputStream("file.pdf"); int len; while ((len = in.read(buffer)) > 0) { zos.write(buffer, 0, len); } in.close(); zos.closeEntry(); zos.close(); } catch(IOException ex) { ex.printStackTrace(); }
поскольку мне потребовалось некоторое время, чтобы понять это, я подумал, что было бы полезно опубликовать мое решение с помощью Java 7+ ZipFileSystem
openZip(runFile); addToZip(filepath); //loop construct; zipfs.close(); private void openZip(File runFile) throws IOException { Map<String, String> env = new HashMap<>(); env.put("create", "true"); env.put("encoding", "UTF-8"); Files.deleteIfExists(runFile.toPath()); zipfs = FileSystems.newFileSystem(URI.create("jar:" + runFile.toURI().toString()), env); } private void addToZip(String filename) throws IOException { Path externalTxtFile = Paths.get(filename).toAbsolutePath(); Path pathInZipfile = zipfs.getPath(filename.substring(filename.lastIndexOf("results"))); //all files to be stored have a common base folder, results/ in my case if (Files.isDirectory(externalTxtFile)) { Files.createDirectories(pathInZipfile); try (DirectoryStream<Path> ds = Files.newDirectoryStream(externalTxtFile)) { for (Path child : ds) { addToZip(child.normalize().toString()); //recursive call } } } else { // copy file to zip file Files.copy(externalTxtFile, pathInZipfile, StandardCopyOption.REPLACE_EXISTING); } }