使用Java将文件附加到zip文件

使用Java将文件附加到zip文件,java,zip,war,truezip,Java,Zip,War,Truezip,我目前正在提取一个war文件的内容,然后将一些新文件添加到目录结构中,然后创建一个新的war文件 这一切都是通过Java编程完成的——但我想知道复制war文件然后仅仅附加文件是否会更有效——这样我就不必等待war扩展,然后再次压缩 我似乎在文档或任何在线示例中都找不到这样做的方法 有人能给我一些建议吗 更新: 其中一个答案中提到的TrueZip似乎是一个非常好的java库,可以附加到zip文件中(尽管其他答案说这是不可能的) 任何人对TrueZip有经验或反馈,或者可以推荐其他类似的库?请参见此

我目前正在提取一个war文件的内容,然后将一些新文件添加到目录结构中,然后创建一个新的war文件

这一切都是通过Java编程完成的——但我想知道复制war文件然后仅仅附加文件是否会更有效——这样我就不必等待war扩展,然后再次压缩

我似乎在文档或任何在线示例中都找不到这样做的方法

有人能给我一些建议吗

更新:

其中一个答案中提到的TrueZip似乎是一个非常好的java库,可以附加到zip文件中(尽管其他答案说这是不可能的)

任何人对TrueZip有经验或反馈,或者可以推荐其他类似的库?

请参见此

在任何类型的应用程序上使用append模式 结构化数据,如zip文件或tar 文件不是你真正能做的事情 期待工作。这些文件格式 具有内在的“文件结尾” 数据格式中内置的指示


如果您真的想跳过解除警告/重新警告的中间步骤,您可以读取war文件,获取所有zip条目,然后将要添加的新条目“附加”到一个新的war文件中。不完美,但至少是一个自动化程度更高的解决方案。

我不知道有哪一个Java库能做到您所描述的。但你所描述的是实际的。您可以在.NET中使用

Michael Krauklis的观点是正确的,您不能简单地将数据“附加”到war文件或zip文件,但严格来说,这并不是因为war文件中有“文件结束”指示。这是因为war(zip)格式包含一个目录,该目录通常位于文件末尾,其中包含war文件中各种条目的元数据。简单地附加到war文件不会导致目录的更新,因此您只会得到一个附加了垃圾的war文件


需要的是一个理解格式的智能类,可以读取并更新war文件或zip文件,包括适当的目录。DotNetZip可以做到这一点,而无需解压缩/重新压缩未更改的条目,正如您所描述或希望的那样

正如奇索所说,没有办法做到这一点。AFAIK的拉链前端做的和你内部一样

无论如何,如果您担心提取/压缩所有内容的速度,您可能需要尝试使用库

我在几个月前的一篇文章中谈到了这个图书馆(很抱歉汽车促销)。例如,使用java.util.zip提取一个104MB的zip文件需要12秒,而使用这个库需要4秒

在这两个链接中,您可以找到有关如何使用它的示例


希望它能有所帮助。

我以前也有类似的要求,但它是用于阅读和编写zip档案的(.war格式应该类似)。我试着用现有的JavaZIP流来做这件事,但发现编写部分很麻烦——特别是当涉及目录时


我建议您尝试使用(开放源代码-apache风格许可)库,它将任何存档公开为一个虚拟文件系统,您可以像普通文件系统一样在其中读写。它对我来说很有魅力,大大简化了我的发展

正如其他人提到的,不可能将内容附加到现有的zip(或war)中。但是,可以动态创建新的zip,而无需将提取的内容临时写入磁盘。很难猜测这会快多少,但这是标准Java所能达到的最快速度(至少据我所知)。正如Carlos Tasada所提到的,SevenZipJBindings可能会为您挤出一些额外的时间,但是将这种方法移植到SevenZipJBindings仍然比在同一个库中使用临时文件要快

下面是一些代码,用于写入现有zip(war.zip)的内容,并将一个额外的文件(answer.txt)附加到一个新的zip(append.zip)中。它只需要Java5或更高版本,不需要额外的库

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;

public class Main {

    // 4MB buffer
    private static final byte[] BUFFER = new byte[4096 * 1024];

    /**
     * copy input to output stream - available in several StreamUtils or Streams classes 
     */    
    public static void copy(InputStream input, OutputStream output) throws IOException {
        int bytesRead;
        while ((bytesRead = input.read(BUFFER))!= -1) {
            output.write(BUFFER, 0, bytesRead);
        }
    }

    public static void main(String[] args) throws Exception {
        // read war.zip and write to append.zip
        ZipFile war = new ZipFile("war.zip");
        ZipOutputStream append = new ZipOutputStream(new FileOutputStream("append.zip"));

        // first, copy contents from existing war
        Enumeration<? extends ZipEntry> entries = war.entries();
        while (entries.hasMoreElements()) {
            ZipEntry e = entries.nextElement();
            System.out.println("copy: " + e.getName());
            append.putNextEntry(e);
            if (!e.isDirectory()) {
                copy(war.getInputStream(e), append);
            }
            append.closeEntry();
        }

        // now append some extra content
        ZipEntry e = new ZipEntry("answer.txt");
        System.out.println("append: " + e.getName());
        append.putNextEntry(e);
        append.write("42\n".getBytes());
        append.closeEntry();

        // close
        war.close();
        append.close();
    }
}
导入java.io.File;
导入java.io.FileOutputStream;
导入java.io.IOException;
导入java.io.InputStream;
导入java.io.OutputStream;
导入java.util.Enumeration;
导入java.util.zip.ZipEntry;
导入java.util.zip.ZipFile;
导入java.util.zip.ZipoutStream;
公共班机{
//4MB缓冲区
私有静态最终字节[]缓冲区=新字节[4096*1024];
/**
*将输入复制到输出流-在多个StreamUtils或Streams类中可用
*/    
公共静态无效复制(InputStream输入、OutputStream输出)引发IOException{
int字节读取;
而((bytesRead=input.read(BUFFER))!=-1){
输出写入(缓冲区,0,字节读取);
}
}
公共静态void main(字符串[]args)引发异常{
//读取war.zip并写入append.zip
ZipFile war=新ZipFile(“war.zip”);
ZipOutputStream append=newzipoutpstream(newfileoutputstream(“append.zip”));
//首先,复制现有war中的内容

枚举另一种解决方案:您可能会发现下面的代码在其他情况下也很有用

    public static void antUpdateZip(String zipFilePath, String libsToAddDir) {
    Project p = new Project();
    p.init();

    Target target = new Target();
    target.setName("zip");
    Zip task = new Zip();
    task.init();
    task.setDestFile(new File(zipFilePath));
    ZipFileSet zipFileSet = new ZipFileSet();
    zipFileSet.setPrefix("WEB-INF/lib");
    zipFileSet.setDir(new File(libsToAddDir));
    task.addFileset(zipFileSet);
    task.setUpdate(true);

    task.setProject(p);
    task.init();
    target.addTask(task);
    target.setProject(p);
    p.addTarget(target);

    DefaultLogger consoleLogger = new DefaultLogger();
    consoleLogger.setErrorPrintStream(System.err);
    consoleLogger.setOutputPrintStream(System.out);
    consoleLogger.setMessageOutputLevel(Project.MSG_DEBUG);
    p.addBuildListener(consoleLogger);

    try {
        // p.fireBuildStarted();

        // ProjectHelper helper = ProjectHelper.getProjectHelper();
        // p.addReference("ant.projectHelper", helper);
        // helper.parse(p, buildFile);
        p.executeTarget(target.getName());
        // p.fireBuildFinished(null);
    } catch (BuildException e) {
        p.fireBuildFinished(e);
        throw new AssertionError(e);
    }
}

你可以使用我写的这段代码

public static void addFilesToZip(File source, File[] files)
{
    try
    {

        File tmpZip = File.createTempFile(source.getName(), null);
        tmpZip.delete();
        if(!source.renameTo(tmpZip))
        {
            throw new Exception("Could not make temp file (" + source.getName() + ")");
        }
        byte[] buffer = new byte[1024];
        ZipInputStream zin = new ZipInputStream(new FileInputStream(tmpZip));
        ZipOutputStream out = new ZipOutputStream(new FileOutputStream(source));

        for(int i = 0; i < files.length; i++)
        {
            InputStream in = new FileInputStream(files[i]);
            out.putNextEntry(new ZipEntry(files[i].getName()));
            for(int read = in.read(buffer); read > -1; read = in.read(buffer))
            {
                out.write(buffer, 0, read);
            }
            out.closeEntry();
            in.close();
        }

        for(ZipEntry ze = zin.getNextEntry(); ze != null; ze = zin.getNextEntry())
        {
            out.putNextEntry(ze);
            for(int read = zin.read(buffer); read > -1; read = zin.read(buffer))
            {
                out.write(buffer, 0, read);
            }
            out.closeEntry();
        }

        out.close();
        tmpZip.delete();
    }
    catch(Exception e)
    {
        e.printStackTrace();
    }
}
publicstaticvoid addFilesToZip(文件源,文件[]文件)
{
尝试
{
文件tmpZip=File.createTempFile(source.getName(),null);
tmpZip.delete();
如果(!source.renameTo(tmpZip))
{
抛出新异常(“无法生成临时文件(“+source.getName()+”);
}
字节[]缓冲区=新字节[1024];
ZipInputStream zin=新的ZipInputStream(新文件输入流(tmpZip));
ZipOutputStream out=新的zipoutpstream(新文件输出流(源));
对于(int i=0;iMap<String, String> env = new HashMap<>(); 
env.put("create", "true");
Path path = Paths.get("test.zip");
URI uri = URI.create("jar:" + path.toUri());
try (FileSystem fs = FileSystems.newFileSystem(uri, env))
{
    Path nf = fs.getPath("new.txt");
    try (Writer writer = Files.newBufferedWriter(nf, StandardCharsets.UTF_8, StandardOpenOption.CREATE)) {
        writer.write("hello");
    }
}
  /**
   * Modifies, adds or deletes file(s) from a existing zip file.
   *
   * @param zipFile the original zip file
   * @param newZipFile the destination zip file
   * @param filesToAddOrOverwrite the names of the files to add or modify from the original file
   * @param filesToAddOrOverwriteInputStreams the input streams containing the content of the files
   * to add or modify from the original file
   * @param filesToDelete the names of the files to delete from the original file
   * @throws IOException if the new file could not be written
   */
  public static void modifyZipFile(File zipFile,
      File newZipFile,
      String[] filesToAddOrOverwrite,
      InputStream[] filesToAddOrOverwriteInputStreams,
      String[] filesToDelete) throws IOException {


    try (ZipOutputStream out = new ZipOutputStream(new FileOutputStream(newZipFile))) {

      // add existing ZIP entry to output stream
      try (ZipInputStream zin = new ZipInputStream(new FileInputStream(zipFile))) {
        ZipEntry entry = null;
        while ((entry = zin.getNextEntry()) != null) {
          String name = entry.getName();

          // check if the file should be deleted
          if (filesToDelete != null) {
            boolean ignoreFile = false;
            for (String fileToDelete : filesToDelete) {
              if (name.equalsIgnoreCase(fileToDelete)) {
                ignoreFile = true;
                break;
              }
            }
            if (ignoreFile) {
              continue;
            }
          }

          // check if the file should be kept as it is
          boolean keepFileUnchanged = true;
          if (filesToAddOrOverwrite != null) {
            for (String fileToAddOrOverwrite : filesToAddOrOverwrite) {
              if (name.equalsIgnoreCase(fileToAddOrOverwrite)) {
                keepFileUnchanged = false;
              }
            }
          }

          if (keepFileUnchanged) {
            // copy the file as it is
            out.putNextEntry(new ZipEntry(name));
            IOUtils.copy(zin, out);
          }
        }
      }

      // add the modified or added files to the zip file
      if (filesToAddOrOverwrite != null) {
        for (int i = 0; i < filesToAddOrOverwrite.length; i++) {
          String fileToAddOrOverwrite = filesToAddOrOverwrite[i];
          try (InputStream in = filesToAddOrOverwriteInputStreams[i]) {
            out.putNextEntry(new ZipEntry(fileToAddOrOverwrite));
            IOUtils.copy(in, out);
            out.closeEntry();
          }
        }
      }

    }

  }
myZipPath = bla bla...
    byte[] buf = new byte[8192];
    String zipName = "myZip.zip";
    String zipPath = myzippath+ File.separator+"pdf" + File.separator+ zipName;
    File pdfFile = new File("myPdf.pdf");
    ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipPath));
    ZipEntry zipEntry = new ZipEntry(pdfFile.getName());
    out.putNextEntry(zipEntry);
    InputStream in = new FileInputStream(pdfFile);
    int len;
    while ((len = in.read(buf)) > 0) {
         out.write(buf, 0, len);
     }
    out.closeEntry();
    in.close();
     out.close();
                FileInputStream fis = new FileInputStream(zipPath);
                response.setContentType("application/zip");
                response.addHeader("content-disposition", "attachment;filename=" + zipName);
    OutputStream os = response.getOutputStream();
            int length = is.read(buffer);
            while (length != -1)
            {
                os.write(buffer, 0, length);
                length = is.read(buffer);
            }
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class AddZip {

    public void AddZip() {
    }

    public void addToZipFile(ZipOutputStream zos, String nombreFileAnadir, String nombreDentroZip) {
        FileInputStream fis = null;
        try {
            if (!new File(nombreFileAnadir).exists()) {//NO EXISTE 
                System.out.println(" No existe el archivo :  " + nombreFileAnadir);return;
            }
            File file = new File(nombreFileAnadir);
            System.out.println(" Generando el archivo '" + nombreFileAnadir + "' al ZIP ");
            fis = new FileInputStream(file);
            ZipEntry zipEntry = new ZipEntry(nombreDentroZip);
            zos.putNextEntry(zipEntry);
            byte[] bytes = new byte[1024];
            int length;
            while ((length = fis.read(bytes)) >= 0) {zos.write(bytes, 0, length);}
            zos.closeEntry();
            fis.close();

        } catch (FileNotFoundException ex ) {
            Logger.getLogger(AddZip.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(AddZip.class.getName()).log(Level.SEVERE, null, ex);
        } 
    }

}
//in the top
try {
fos = new FileOutputStream(rutaZip);
zos =   new ZipOutputStream(fos);
} catch (FileNotFoundException ex) {
Logger.getLogger(UtilZip.class.getName()).log(Level.SEVERE, null, ex);
}

...
//inside your method
addZip.addToZipFile(zos, pathFolderFileSystemHD() + itemFoto.getNombre(), "foto/" + itemFoto.getNombre());
// append a file to archive under different name
TFile.cp(new File("existingFile.txt"), new TFile("archive.zip", "entry.txt"));

// recusively append a dir to the root of archive
TFile src = new TFile("dirPath", "dirName");
src.cp_r(new TFile("archive.zip", src.getName()));
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    Resource resourceFile = resourceLoader.getResource("WEB-INF/lib/custom.jar");
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    try (ZipOutputStream zos = new ZipOutputStream(baos, StandardCharsets.ISO_8859_1);) {
        try (ZipFile zin = new ZipFile(resourceFile.getFile(), StandardCharsets.ISO_8859_1);) {
            zin.stream().forEach((entry) -> {
                try {
                    zos.putNextEntry(entry);
                    if (!entry.isDirectory()) {
                        zin.getInputStream(entry).transferTo(zos);
                    }
                    zos.closeEntry();
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            });
        }
        /* build file records to be appended */
        ....
        for (FileContents record : records) {
            zos.putNextEntry(new ZipEntry(record.getFileName()));
            zos.write(record.getBytes());
            zos.closeEntry();
        }
        zos.flush();
    }

    response.setContentType("application/java-archive");
    response.setContentLength(baos.size());
    response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"custom.jar\"");
    try (BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream())) {
        baos.writeTo(out);
    }
}