Java'da zip dosyası nasıl oluşturulur


149

Kullanıcının sorgusuna göre bir veritabanından içerik alır dinamik bir metin dosyası var. Bu içeriği bir metin dosyasına yazmak ve sunucu uygulamasındaki bir klasöre sıkıştırmak zorundayım. Bunu nasıl yapmalıyım?

Yanıtlar:


231

Şu örneğe bakın:

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();

Bu, D:adlandırılmış kök adında test.zipbir tek dosya içeren bir zip oluşturur mytext.txt. Tabii ki daha fazla zip girişi ekleyebilir ve ayrıca bunun gibi bir alt dizin belirleyebilirsiniz:

ZipEntry e = new ZipEntry("folderName/mytext.txt");

Java ile sıkıştırma hakkında daha fazla bilgiyi burada bulabilirsiniz .


1
Neden iki satır: byte[] data = sb.toString().getBytes(); out.write(data, 0, data.length);bu kod örneğine dahil edildi? Amaçları nedir?
Kaadzia

@kdzia, ilk satır StringBuilder değerini bir bayt dizisine dönüştürür ve ikinci satır da bu bayt dizisini alır ve bunu "test.zip" dosyası içinde ZipEntry'ye yazar. Bu satırlar gereklidir, çünkü Zip dosyaları dizelerle değil bayt dizileriyle çalışır.
OrangeWombat

3
Ancak ... yukarıdaki örnekte, StringBuilder içinde "Test Dizesi" dışında bir şey var mı? Ben de bununla biraz kafam karıştı. sb.toString().getBytes()ZIP dosyasına yazıyorsanız, sıkıştırdığınız dosyanın baytlarını içermesini ister misiniz? Yoksa bir şey mi kaçırıyorum?
RobA

3
@RobA hiçbir şeyi kaçırmıyorsunuz. StringBuilder gerçekten OP'nin veritabanından aldığı metni içermelidir. OP sadece getTextFromDatabase () gibi bir şey için "Test Dizesi" (tırnak işaretleri dahil) değiştirmek zorunda
kalacak

Teşekkürler, @Blueriver
RobA

143

Java 7, zip dosyasından dosya oluşturmak, yazmak ve okumak için kullanılabilen yerleşik ZipFileSystem'a sahiptir.

Java Belgesi: ZipFileSystem Sağlayıcısı

Map<String, String> env = new HashMap<>();
// Create the zip file if it doesn't exist
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); 
}

1
Uzantı yoksa bu çalışmanın bir yolu var mı .zip? Bir yazmanız gerekir .fooancak farklı uzantılı, tam bir zip dosyası gibi biçimlendirilir dosyayı. Bir .zipdosya yapıp yeniden adlandırabileceğimi biliyorum, ama sadece doğru adla oluşturmak daha kolay olurdu.
Troy Daniels

2
@TroyDaniels, jar:file:URI oluşturmak için önekini kullandığından, yukarıdaki örnek farklı uzantılarla da çalışır .
Sivabalan

10
Burada görünebilecek tek sorun, dizinleriniz olması durumunda çalışmayacağıdır. Bu nedenle, örneğin, pathInZipfiledeğişkente "/dir/SomeTextFile.txt" varsa , .zip arşivinin içinde 'dir' oluşturmanız gerekir. Bunun için, bir sonraki satırı ekleyin: Files.createDirectories(pathInZipfile.getParent())invoke Files.copyyönteminden önce .
D.Naumovich

sıkıştırma seviyesi nasıl ayarlanır?
cdalxndr

34

Bir ZIP dosyası yazmak için bir ZipOutputStream kullanırsınız. ZIP dosyasına yerleştirmek istediğiniz her giriş için bir ZipEntry nesnesi oluşturursunuz. Dosya adını ZipEntry yapıcısına iletirsiniz; dosya tarihi ve açma yöntemi gibi diğer parametreleri ayarlar. İsterseniz bu ayarları geçersiz kılabilirsiniz. Ardından, yeni bir dosya yazmaya başlamak için ZipOutputStream öğesinin putNextEntry yöntemini çağırın. Dosya verilerini ZIP akışına gönderin. İşiniz bittiğinde closeEntry'i arayın. Saklamak istediğiniz tüm dosyalar için tekrarlayın. İşte bir kod iskeleti:

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();

22

Tüm Dizini (alt dosyalar ve alt dizinler dahil) sıkıştırmak için bir örnek kod , Java NIO'nun yürüyüş dosyası ağacı özelliğini kullanıyor.

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) {
        final Path sourceDir = Paths.get(dirPath);
        String zipFileName = dirPath.concat(".zip");
        try {
            final 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();
        }
    }
}

Bunu kullanmak için

ZipCompress.compress("target/directoryToCompress");

ve bir zip dosyası dizini alacaksınız


4

Bahar önyükleme denetleyicisi, bir dizindeki dosyaları zip ve indirilebilir.

@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();
}

2
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");
    }
 }    

}

2

Kaynak dosyadan bir zip dosyası şu şekilde oluşturulur:

String srcFilename = "C:/myfile.txt";
String zipFile = "C:/myfile.zip";

try {
    byte[] buffer = new byte[1024];
    FileOutputStream fos = new FileOutputStream(zipFile);
    ZipOutputStream zos = new ZipOutputStream(fos);         
    File srcFile = new File(srcFilename);
    FileInputStream fis = new FileInputStream(srcFile);
    zos.putNextEntry(new ZipEntry(srcFile.getName()));          
    int length;
    while ((length = fis.read(buffer)) > 0) {
        zos.write(buffer, 0, length);
    }
    zos.closeEntry();
    fis.close();
    zos.close();            
}
catch (IOException ioe) {
    System.out.println("Error creating zip file" + ioe);
}

1

Tek dosya:

String filePath = "/absolute/path/file1.txt";
String zipPath = "/absolute/path/output.zip";

try (ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(zipPath))) {
    File fileToZip = new File(filePath);
    zipOut.putNextEntry(new ZipEntry(fileToZip.getName()));
    Files.copy(fileToZip.toPath(), zipOut);
}

Birden çok dosya:

List<String> filePaths = Arrays.asList("/absolute/path/file1.txt", "/absolute/path/file2.txt");
String zipPath = "/absolute/path/output.zip";

try (ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(zipPath))) {
    for (String filePath : filePaths) {
        File fileToZip = new File(filePath);
        zipOut.putNextEntry(new ZipEntry(fileToZip.getName()));
        Files.copy(fileToZip.toPath(), zipOut);
    }
}

1

Temel olarak iki işlev oluşturmanız gerekir. Birincisi writeToZipFile () ve ikincisi createZipfileForOutPut .... ve daha sonra createZipfileForOutPut ('.zip' 'dosya adı) ``

 public static void writeToZipFile(String path, ZipOutputStream zipStream)
        throws FileNotFoundException, IOException {

    System.out.println("Writing file : '" + path + "' to zip file");

    File aFile = new File(path);
    FileInputStream fis = new FileInputStream(aFile);
    ZipEntry zipEntry = new ZipEntry(path);
    zipStream.putNextEntry(zipEntry);

    byte[] bytes = new byte[1024];
    int length;
    while ((length = fis.read(bytes)) >= 0) {
        zipStream.write(bytes, 0, length);
    }

    zipStream.closeEntry();
    fis.close();
}

public static void createZipfileForOutPut(String filename) {
    String home = System.getProperty("user.home");
   // File directory = new File(home + "/Documents/" + "AutomationReport");
    File directory = new File("AutomationReport");
    if (!directory.exists()) {
        directory.mkdir();
    }
    try {
        FileOutputStream fos = new FileOutputStream("Path to your destination" + filename + ".zip");
        ZipOutputStream zos = new ZipOutputStream(fos);

        writeToZipFile("Path to file which you want to compress / zip", zos);


        zos.close();
        fos.close();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

0

Yazılım olmadan sıkıştırmak istiyorsanız bu kodu kullanın. Pdf dosyaları ile diğer kod elle sıkıştırmasını açma hatası gönderir

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();
    }

0

Bunu çözmem biraz zaman aldığından, çözümümü Java 7+ ZipFileSystem kullanarak göndermenin yararlı olacağını düşündüm

 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);            
    }
 }

0
public static void zipFromTxt(String zipFilePath, String txtFilePath) {
    Assert.notNull(zipFilePath, "Zip file path is required");
    Assert.notNull(txtFilePath, "Txt file path is required");
    zipFromTxt(new File(zipFilePath), new File(txtFilePath));
}

public static void zipFromTxt(File zipFile, File txtFile) {
    ZipOutputStream out = null;
    FileInputStream in = null;
    try {
        Assert.notNull(zipFile, "Zip file is required");
        Assert.notNull(txtFile, "Txt file is required");
        out = new ZipOutputStream(new FileOutputStream(zipFile));
        in = new FileInputStream(txtFile);
        out.putNextEntry(new ZipEntry(txtFile.getName()));
        int len;
        byte[] buffer = new byte[1024];
        while ((len = in.read(buffer)) > 0) {
            out.write(buffer, 0, len);
            out.flush();
        }
    } catch (Exception e) {
        log.info("Zip from txt occur error,Detail message:{}", e.toString());
    } finally {
        try {
            if (in != null) in.close();
            if (out != null) {
                out.closeEntry();
                out.close();
            }
        } catch (Exception e) {
            log.info("Zip from txt close error,Detail message:{}", e.toString());
        }
    }
}

0

Verilen exportPathve queryResultsString değişkenleri olarak, aşağıdaki blok results.zipaltında bir dosya oluşturur exportPathve içeriğini zip içindeki queryResultsbir results.txtdosyaya yazar .

URI uri = URI.create("jar:file:" + exportPath + "/results.zip");
Map<String, String> env = Collections.singletonMap("create", "true");

try (FileSystem zipfs = FileSystems.newFileSystem(uri, env)) {
  Path filePath = zipfs.getPath("/results.txt");
  byte[] fileContent = queryResults.getBytes();

  Files.write(filePath, fileContent, StandardOpenOption.CREATE);
}

0

Jeka https://jeka.dev JkPathTree'yi kullanmak oldukça basittir.

Path wholeDirToZip = Paths.get("dir/to/zip");
Path zipFile = Paths.get("file.zip");
JkPathTree.of(wholeDirToZip).zipTo(zipFile);

0

Kullanarak başka seçeneği yoktur zip4jaz https://github.com/srikanth-lingala/zip4j

İçinde tek dosya bulunan bir zip dosyası oluşturma / Varolan bir zip'e tek dosya ekleme

new ZipFile("filename.zip").addFile("filename.ext"); Veya

new ZipFile("filename.zip").addFile(new File("filename.ext"));

Birden çok dosya içeren bir zip dosyası oluşturma / Mevcut bir zip'e birden çok dosya ekleme

new ZipFile("filename.zip").addFiles(Arrays.asList(new File("first_file"), new File("second_file")));

Bir klasör ekleyerek bir zip dosyası oluşturma / Mevcut bir zip'e klasör ekleme

new ZipFile("filename.zip").addFolder(new File("/user/myuser/folder_to_add"));

Akıştan bir zip dosyası oluşturma / Mevcut bir zip'e akış ekleme new ZipFile("filename.zip").addStream(inputStream, new ZipParameters());

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.