Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/383.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在java中实用地从jar中删除特定的文件/文件夹_Java_Jar_Unjar - Fatal编程技术网

如何在java中实用地从jar中删除特定的文件/文件夹

如何在java中实用地从jar中删除特定的文件/文件夹,java,jar,unjar,Java,Jar,Unjar,在java中,如何实用地从jar中删除特定的文件/文件夹 我有一个jar ABC.jar包含文件、文件夹和另一个jar称为child.jar。 在child.jar下,我想删除一个特定的文件。我该怎么办?所以我的ABC.jar结构保持不变 任何帮助都将不胜感激 提前谢谢 Jar/zip文件不可编辑。不能从jar/zip文件中删除条目 您可以这样“重新创建”jar文件:启动一个新的jar文件,迭代当前jar文件的条目,并将这些条目添加到您不想删除的新jar文件中 从理论上讲,可以删除这样的条目(

在java中,如何实用地从jar中删除特定的文件/文件夹

我有一个jar ABC.jar包含文件、文件夹和另一个jar称为child.jar。 在child.jar下,我想删除一个特定的文件。我该怎么办?所以我的ABC.jar结构保持不变

任何帮助都将不胜感激


提前谢谢

Jar/zip文件不可编辑。不能从jar/zip文件中删除条目

您可以这样“重新创建”jar文件:启动一个新的jar文件,迭代当前jar文件的条目,并将这些条目添加到您不想删除的新jar文件中


从理论上讲,可以删除这样的条目(但标准Java库不适用于此,这意味着
ZipFile
ZipInputStream
JarFile
JarInputStream
类):

jar/zip文件中的条目是顺序的。每个条目都有一个标题,其中包含关于该条目的信息(可能是文件或文件夹条目)。此标头还包含条目的字节长度。因此,您可以依次迭代条目,如果遇到要删除的条目(并且您从其标题中知道其大小),则可以将文件的剩余部分(该条目之后的内容)复制到当前条目的开头(显然,文件大小应根据当前/已删除条目的长度进行调整)



或者您的其他选择包括不通过Java执行此操作,而是使用外部工具,如
zip-d
命令本身。

Sun/Oracle bug数据库要求在Java api中实现此功能


检查

正如@icza所回答的,我们必须遍历原始jar文件并删除我们不想要的条目。 下面是您可以参考的java代码

 public static void main(String[] args) throws IOException {


  String jarName = args[0];
  String fileName = args[1];

  // Create file descriptors for the jar and a temp jar.

  File jarFile = new File(jarName);
  File tempJarFile = new File(jarName + ".tmp");

  // Open the jar file.

  JarFile jar = new JarFile(jarFile);
  System.out.println(jarName + " opened.");

  // Initialize a flag that will indicate that the jar was updated.

  boolean jarUpdated = false;

  try {
     // Create a temp jar file with no manifest. (The manifest will
     // be copied when the entries are copied.)

     Manifest jarManifest = jar.getManifest();
     JarOutputStream tempJar =
        new JarOutputStream(new FileOutputStream(tempJarFile));

     // Allocate a buffer for reading entry data.

     byte[] buffer = new byte[1024];
     int bytesRead;

     try {
        // Open the given file.

        FileInputStream file = new FileInputStream(fileName);

        try {
           // Create a jar entry and add it to the temp jar.

           JarEntry entry = new JarEntry(fileName);
           tempJar.putNextEntry(entry);

           // Read the file and write it to the jar.

           while ((bytesRead = file.read(buffer)) != -1) {
              tempJar.write(buffer, 0, bytesRead);
           }

           System.out.println(entry.getName() + " added.");
        }
        finally {
           file.close();
        }

        // Loop through the jar entries and add them to the temp jar,
        // skipping the entry that was added to the temp jar already.

        for (Enumeration entries = jar.entries(); entries.hasMoreElements(); ) {
           // Get the next entry.

           JarEntry entry = (JarEntry) entries.nextElement();

           // If the entry has not been added already, add it.

           if (! entry.getName().equals(fileName)) {
              // Get an input stream for the entry.

              InputStream entryStream = jar.getInputStream(entry);

              // Read the entry and write it to the temp jar.

              tempJar.putNextEntry(entry);

              while ((bytesRead = entryStream.read(buffer)) != -1) {
                 tempJar.write(buffer, 0, bytesRead);
              }
           }
        }

        jarUpdated = true;
     }
     catch (Exception ex) {
        System.out.println(ex);

        // Add a stub entry here, so that the jar will close without an
        // exception.

        tempJar.putNextEntry(new JarEntry("stub"));
     }
     finally {
        tempJar.close();
     }
  }
  finally {
     jar.close();
     System.out.println(jarName + " closed.");

     // If the jar was not updated, delete the temp jar file.

     if (! jarUpdated) {
        tempJarFile.delete();
     }
  }

  // If the jar was updated, delete the original jar file and rename the
  // temp jar file to the original name.

  if (jarUpdated) {
     jarFile.delete();
     tempJarFile.renameTo(jarFile);
     System.out.println(jarName + " updated.");
  }

}

有一种简单的方法可以通过在运行时执行命令shell从JAR中删除文件。 执行以下命令将执行以下任务:

Runtime.getRuntime().exec("zip -d path\my.jar some_file.txt");
其中path是jar文件的绝对路径,some_file.txt是要删除的文件。在本例中,文件位于jar的主文件夹中。如果文件位于其他文件夹中,则可能需要提供其相对路径

jar本身的路径您可能提前知道,或者可以根据您正在执行命令shell的类相对地找到它:

String path = SomeClass.class.getProtectionDomain().getCodeSource().getLocation().getPath();
您可以通过侦听可用流来跟踪流程的执行:

    Process p = Runtime.getRuntime().exec("zip -d path\my.jar some_file.txt");
    BufferedReader reader = 
            new BufferedReader(new InputStreamReader(p.getInputStream()));

       String line = "";    
       StringBuilder sb = new StringBuilder();
       while ((line = reader.readLine())!= null) {
           sb.append(line + "\n");
           System.out.println(line);
       }
       System.out.println(sb.toString());
publicstaticvoidfilterjar(路径jarInFileName,字符串skipRegex,路径jarOutFileName)抛出IOException{
ZipEntry入口;
ZipInputStream zis=null;
JarOutputStream os=null;
FileInputStream为空;
试一试{
is=新文件输入流(jarInFileName.toFile());
Pattern=Pattern.compile(skipRegex);
zis=新的ZipInputStream(is);
os=new-JarOutputStream(new-FileOutputStream(jarOutFileName.toFile());
而((entry=zis.getNextEntry())!=null){
如果(pattern.matcher(entry.getName()).matches()继续;
os.Putnextery(条目);
如果(!entry.isDirectory()){
字节[]字节=总字节(zis);
写操作(字节);
}
}
}
捕获(例外情况除外){
抛出新IOException(“无法筛选jar:+ex.getMessage());
}
最后{
关闭(is);
关闭(os);
}
}
公共静态无效安静关闭(最终可关闭){
试一试{
如果(可关闭!=null){
closeable.close();
}
}
捕获(最终异常e){}
}
公共静态字节[]toBytes(InputStream aInput)引发IOException{
字节[]桶=新字节[5*1024];
ByteArrayOutputStream结果=null;
结果=新的ByteArrayOutputStream(bucket.length);
int字节读取=0;
while(字节读取!=-1){
bytesRead=aInput.read(bucket);
如果(字节读取>0){
结果.写入(bucket,0,bytesRead);
}
}
返回result.toByteArray();
}
公共静态void main(字符串[]args)引发IOException{
filterJar(path.get(“./old.jar”),“BOOT-INF/lib.*”,path.get(“./new.jar”);
}

Jar是zip格式的,所以您可以随时解压缩Jar,删除您想要删除的内容,然后压缩回Jar。Java有用于管理zip文件的util包:您必须将内容从源Jar复制到临时Jar,跳过您不想要的内容,删除原始Jar并将tmp重命名回原来的位置…我想在递归模式下执行。可能的重复感谢icza的建议。你能帮我介绍一下这个示例程序吗?哪一个?“重新创建”或“理论”解决方案?缺陷提交日期:“1998-04-16”。。。今天的日期:“2014-08-22”。。。拥有它会很酷,但在本世纪我不会指望它。@Raj Kantaria这不是我所需要的。我怎样才能删除子jar或grand child jar中的文件?建议的代码只在同一个jar/文件夹中有用,不适用于子jar。我认为最简单的方法是让子jar提供一些静态方法,比如deleteFile(filepath),这样父jar就可以调用我没有得到的。这是什么意思?您可以在child.jar中实现delete方法。当你想删除一些文件时,ABC.jar会调用child.jar->delete()方法。我必须在删除之前提取child.jar?