【问题标题】:How to create a zip file in Java如何在 Java 中创建一个 zip 文件
【发布时间】:2010-11-08 16:08:47
【问题描述】:

我有一个动态文本文件,它根据用户的查询从数据库中挑选内容。我必须将此内容写入文本文件并将其压缩到 servlet 的文件夹中。我该怎么做?

【问题讨论】:

    标签: java zip


    【解决方案1】:

    我知道这个问题已经得到解答,但如果你有一个字符串列表,并且你想为存档中的每个字符串创建一个单独的文件,你可以使用下面的 sn-p。

    public void zipFileTest() throws IOException {
    
        Map<String, String> map = Map.ofEntries(
                new AbstractMap.SimpleEntry<String, String>("File1.txt", "File1 Content"),
                new AbstractMap.SimpleEntry<String, String>("File2.txt", "File2 Content"),
                new AbstractMap.SimpleEntry<String, String>("File3.txt", "File3 Content")
        );
    
        createZipFileFromStringContents(map, "archive.zip");
    
    }
    
    public void createZipFileFromStringContents(Map<String, String> map, String zipfilePath) throws IOException {
    
        FileOutputStream fout = new FileOutputStream(zipfilePath);
        ZipOutputStream zout = new ZipOutputStream(fout);
    
        for (Map.Entry<String, String> entry : map.entrySet()) {
            String fileName = entry.getKey();
            ZipEntry zipFile = new ZipEntry(fileName);
            zout.putNextEntry(zipFile);
            String fileContent = entry.getValue();
            zout.write(fileContent.getBytes(), 0, fileContent.getBytes().length);
            zout.closeEntry();
        }
    
        zout.close();
    }
    

    它将创建一个结构如下图所示的 zip 文件:

    【讨论】:

      【解决方案2】:

      https://github.com/srikanth-lingala/zip4j 处使用zip4j 还有另一种选择

      创建一个包含单个文件的 zip 文件/将单个文件添加到现有 zip 中

      new ZipFile("filename.zip").addFile("filename.ext"); 或者

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

      创建包含多个文件的 zip 文件 / 将多个文件添加到现有 zip 中

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

      通过向其添加文件夹/向现有 zip 添加文件夹来创建 zip 文件

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

      从流创建 zip 文件/将流添加到现有 zip new ZipFile("filename.zip").addStream(inputStream, new ZipParameters());

      【讨论】:

        【解决方案3】:

        使用Jeka https://jeka.devJkPathTree,很简单。

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

        【讨论】:

          【解决方案4】:

          您主要需要创建两个函数。首先是 writeToZipFile(),其次是 createZipfileForOutPut .... 然后调用 createZipfileForOutPut('file name of .zip')` ...

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

          【讨论】:

            【解决方案5】:

            看这个例子:

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

            这将在D: 的根目录中创建一个名为test.zip 的压缩包,其中将包含一个名为mytext.txt 的文件。当然,你可以添加更多的 zip 条目,也可以像这样指定一个子目录:

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

            您可以找到有关使用 Java here 进行压缩的更多信息。

            【讨论】:

            • 为什么这两行:byte[] data = sb.toString().getBytes(); out.write(data, 0, data.length); 包含在此代码示例中?他们的目的是什么?
            • @kdzia,第一行将 StringBuilder 值转换为字节数组,第二行获取该字节数组并将其写入“test.zip”文件中的 ZipEntry。这些行是必要的,因为 Zip 文件使用字节数组,而不是字符串。
            • 但是......在上面的例子中,除了“测试字符串”之外,StringBuilder 中还有什么其他内容吗?我对此也有些困惑。如果您将 sb.toString().getBytes() 写入 ZIP 文件,我希望您希望它包含您正在压缩的文件的字节?还是我错过了什么?
            • @RobA 你没有错过任何东西。 StringBuilder 确实是为了包含 OP 从他的数据库中获得的文本。 OP 只需将“测试字符串”(包括引号)替换为 getTextFromDatabase()
            • 谢谢,@Blueriver
            【解决方案6】:

            Java 7 内置了 ZipFileSystem,可用于从 zip 文件创建、写入和读取文件。

            Java Doc: ZipFileSystem Provider

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

            【讨论】:

            • 如果扩展名不是.zip,有没有办法让它工作?我需要编写一个.foo 文件,其格式与 zip 文件完全相同,但扩展名不同。我知道我可以创建一个.zip 文件并重命名它,但是使用正确的名称创建它会更简单。
            • @TroyDaniels 上面的示例也适用于不同的扩展名,因为它使用 jar:file: 前缀来创建 URI。
            • 这里可能出现的唯一问题是,如果您有目录,它将无法工作。因此,例如,如果 pathInZipfile 变量中有“/dir/SomeTextFile.txt”,则需要在 .zip 存档中创建“dir”。为此,只需在调用 Files.copy 方法之前添加下一行:Files.createDirectories(pathInZipfile.getParent())
            • 如何设置压缩级别?
            【解决方案7】:

            exportPathqueryResults 作为字符串变量,以下代码块在exportPath 下创建一个results.zip 文件,并将queryResults 的内容写入zip 内的results.txt 文件。

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

            【讨论】:

              【解决方案8】:

              这是一个压缩整个目录(包括子文件和子目录)的示例代码,它使用了Java NIO的walk file tree特性。

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

              要使用它,只需调用

              ZipCompress.compress("target/directoryToCompress");
              

              你会得到一个 zip 文件 directoryToCompress.zip

              【讨论】:

              • 如何包含当前目录?
              • 如果输入和输出目录相同,也是再次压缩zip文件。
              【解决方案9】:
              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());
                      }
                  }
              }
              

              【讨论】:

                【解决方案10】:

                单个文件:

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

                多个文件:

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

                【讨论】:

                  【解决方案11】:

                  这是从源文件创建 zip 文件的方式:

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

                  【讨论】:

                    【解决方案12】:

                    由于我花了一段时间才弄清楚,我认为使用 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);            
                        }
                     }
                    

                    【讨论】:

                      【解决方案13】:

                      Spring boot 控制器,将文件压缩到一个目录下,即可下载。

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

                      【讨论】:

                        【解决方案14】:

                        如果您想在没有软件的情况下解压缩,最好使用此代码。其他带有 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();
                            }
                        

                        【讨论】:

                          【解决方案15】:
                          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");
                              }
                           }    
                          
                          }
                          

                          【讨论】:

                            【解决方案16】:

                            要编写 ZIP 文件,请使用 ZipOutputStream。对于要放入 ZIP 文件的每个条目,您都创建一个 ZipEntry 对象。您将文件名传递给 ZipEntry 构造函数;它设置其他参数,例如文件日期和解压缩方法。如果您愿意,可以覆盖这些设置。然后,调用 ZipOutputStream 的 putNextEntry 方法开始写入新文件。将文件数据发送到 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();
                            

                            【讨论】:

                              猜你喜欢
                              • 1970-01-01
                              • 2011-02-27
                              • 1970-01-01
                              • 1970-01-01
                              • 2012-10-16
                              • 1970-01-01
                              • 1970-01-01
                              • 1970-01-01
                              • 2014-06-30
                              相关资源
                              最近更新 更多