JarFile from inside a *.jar or inputstream to file?

后端 未结 4 1610
再見小時候
再見小時候 2021-01-13 23:02

I have a jar or war.

I\'m programmaticaly reading this jar, and when I find jar inside this jar I\'d like to programmaticaly read it again.

But JarFile prov

相关标签:
4条回答
  • 2021-01-13 23:29

    you can create jar file in File System, something like

     File tempFile=TempFile.createFile("newJar",".jar");
    

    and write Stream into it. After that you can construct your JarFile(tempFile) and handle it...

    Forget about it if program is running as unsigned applet/JNLP since you will not have right to create file in file system...

    0 讨论(0)
  • 2021-01-13 23:33

    Recursively use the JarFile again to read the new jar file. For ex.,

    import java.io.File;
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.Enumeration;
    import java.util.jar.JarEntry;
    import java.util.jar.JarFile;
    import java.util.zip.ZipEntry;
    
    
    public class JarReader {
    
    public static void readJar(String jarName) throws IOException {
        String dir = new File(jarName).getParent();
        JarFile jf = new JarFile(jarName);
        Enumeration<JarEntry> en = jf.entries();
        while(en.hasMoreElements()) { 
            ZipEntry ze = (ZipEntry)en.nextElement();
            if(ze.getName().endsWith(".jar")) { 
                readJar(dir + System.getProperty("file.separator") + ze.getName());
            } else {
                InputStream is = jf.getInputStream(ze);
                // ... read from input stream
                is.close();
                System.out.println("Processed class: " + ze.getName());
            }   
        }
    }
    
    public static void main(String[] args) throws IOException {
        readJar(args[0]);
    }
    
    }
    
    0 讨论(0)
  • 2021-01-13 23:39

    Generally it is a matter of getting to an InputStream and then work with that. This allows you to abstract from most "jar in jar on web server" issues and similar.

    Apparently in this case it is JarFile.getInputStream() and JarInputStream().

    0 讨论(0)
  • 2021-01-13 23:48

    Update: Sorry this is probably too late for your needs, I just spotted your last question in the comments though. So I've modified the example to show each nested entry being copied directly to an OutputStream without any need to inflate the outer jar.

    In this case the OutputStream is System.out but it could be any OutputStream (e.g. to a file...).


    There's no need to use a temporary file. You can use JarInputStream instead of JarFile, pass the InputStream from the outer entry to the constructor and you can then read the contents of the jar.

    For example:

    JarFile jarFile = new JarFile(warFile);
    
    Enumeration entries = jarFile.entries();
    
    while (entries.hasMoreElements()) {
        JarEntry jarEntry = (JarEntry) entries.nextElement();
    
        if (jarEntry.getName().endsWith(".jar")) {
            JarInputStream jarIS = new JarInputStream(jarFile
                    .getInputStream(jarEntry));
    
            // iterate the entries, copying the contents of each nested file 
            // to the OutputStream
            JarEntry innerEntry = jarIS.getNextJarEntry();
    
            OutputStream out = System.out;
    
            while (innerEntry != null) {
                copyStream(jarIS, out, innerEntry);
                innerEntry = jarIS.getNextJarEntry();
            }
        }
    }
    
    ...
    
    /**
     * Read all the bytes for the current entry from the input to the output.
     */
    private void copyStream(InputStream in, OutputStream out, JarEntry entry)
            throws IOException {
        byte[] buffer = new byte[1024 * 4];
        long count = 0;
        int n = 0;
        long size = entry.getSize();
        while (-1 != (n = in.read(buffer)) && count < size) {
            out.write(buffer, 0, n);
            count += n;
        }
    }
    
    0 讨论(0)
提交回复
热议问题