读写ZIP&JAR文件
1. ZipEntry 是包括目录的,也就是目录也被当做是一个单独的Entry,在列出它下面的文件之前先列出这个directory entry.
这个在解压ZIP文件的的时候特别有用,我们要先创建这个目录,然后在解压目录下面的文件,否则解压的时候会说目录不存在.
ZipInputStream zis = new ZipInputStream(new FileInputStream("F:\\workspace\\HibernateSrc\\lib\\hibernate3.jar"));
ZipEntry entry = zis.getNextEntry();
2.JarEntry是不包括目录的,只包括class文件对应的entry, 要想访问目录,请使用ZipEntry读取Jar文件.
JarInputStream jis = new JarInputStream(new FileInputStream(mainJar));
JarEntry entry = jis.getNextJarEntry();
3. 往jar文件里写数据的时候,要首先调用jos.putNextEntry(entry);放入一个entry记录,然后调用jos.write(temp, 0, count);往对应的记录写数据.
4. 读entry内容的时候,先要穿件一个JarFile or ZipFile, 然后遍历所有的entry记录,可以直接调用zip.entires()来得到entry的所有记录,也可以对jar&zip文件
创建一个JarInputStream & ZipInputStream 来遍历entry记录, 当选定了entry后,调用JarFile.getInputStream(entry)来拿到对应entry记录的输入流.
下面的蓝色部分代码是读入的操作,红色部分代码是输出的操作
JarFile zipIn = new JarFile(mainJar); InputStream readin = null; JarOutputStream jos = new JarOutputStream(new FileOutputStream("rt.jar")); JarInputStream jis = new JarInputStream(new FileInputStream(mainJar)); JarEntry entry = jis.getNextJarEntry(); while(entry!=null) { String name = entry.getName(); //remove the .class suffix. name = name.substring(0,name.lastIndexOf(".")); if(depencyClass.contains(name)) { //put an entry record and write the binary data jos.putNextEntry(entry); readin = zipIn.getInputStream(entry); byte[] temp = new byte[4096]; int count = readin.read(temp); while (count != -1) { jos.write(temp, 0, count); count = readin.read(temp); } readin.close(); } entry = jis.getNextJarEntry(); } jis.close(); jos.close();
下面是两个例子
ReduceJRE是用来抽取Jar里面特定的class文件到一个新的rt.jar
public class ReduceJRE { public static void main(String[] args) throws Exception { String mainJar = null; String classDenpdencyFile = null; if(args!=null && args.length==2) { mainJar = args[0]; classDenpdencyFile = args[1]; } else { mainJar = "F:\\Program Files\\Java\\jre7\\lib\\rt.jar"; classDenpdencyFile = "F:\\Program Files\\Java\\jre7\\lib\\classdepency.txt"; } List<String> depencyClass = new ArrayList<String>(); BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(classDenpdencyFile))); String templine = br.readLine(); // load all the dependency class and store them in a array list; while(templine!=null) { int end = templine.lastIndexOf("from"); int begin = templine.lastIndexOf("[Loaded")+7; String className = templine.substring(begin,end).replace(".", "/").trim(); depencyClass.add(className); templine= br.readLine(); } JarFile zipIn = new JarFile(mainJar); InputStream readin = null; JarOutputStream jos = new JarOutputStream(new FileOutputStream("rt.jar")); JarInputStream jis = new JarInputStream(new FileInputStream(mainJar)); JarEntry entry = jis.getNextJarEntry(); while(entry!=null) { String name = entry.getName(); //remove the .class suffix. name = name.substring(0,name.lastIndexOf(".")); if(depencyClass.contains(name)) { //put an entry record and write the binary data jos.putNextEntry(entry); readin = zipIn.getInputStream(entry); byte[] temp = new byte[4096]; int count = readin.read(temp); while (count != -1) { jos.write(temp, 0, count); count = readin.read(temp); } readin.close(); } entry = jis.getNextJarEntry(); } jis.close(); jos.close(); } }
extractZIPFile 把spPath指定的ZIP文件解压到destinationDir,如果指定了fileIdentifier,那么久解压指定的文件,否则解压全部文件。
private String extractZIPFile(String spPath, String destinationDir, String fileIdentifier) throws IOException { ZipFile zip = new ZipFile(spPath); String rootfolderPath = null; FileOutputStream fos = null; InputStream readin = null; /*create the destination folder if it is non-existed.*/ File destFolder = new File(destinationDir); if (!destFolder.exists()) { destFolder.mkdirs(); } try { for (Enumeration<? extends ZipEntry> enums = zip.entries(); enums.hasMoreElements(); ) { ZipEntry entry = (ZipEntry) enums.nextElement(); /*if specified the identifier and the current entry does not match it. then just skip this entry*/ if (fileIdentifier != null) { if (!entry.getName().contains(fileIdentifier)) { continue; } else { String fileName = destinationDir + separator + entry.getName().substring(entry.getName().lastIndexOf("/")); File f = new File(fileName); rootfolderPath = f.getCanonicalPath(); readin = zip.getInputStream(entry); fos = new FileOutputStream(f); byte[] temp = new byte[BUFFER_SIZE]; int count = readin.read(temp); while (count != -1) { fos.write(temp, 0, count); count = readin.read(temp); } /*need to close the fos/readin as the fos/readin will be refer to another entry next time*/ fos.close(); readin.close(); } } else { String fileName = destinationDir + separator + entry.getName(); File f = new File(fileName); if (entry.isDirectory()) { f.mkdirs(); if (rootfolderPath == null) { rootfolderPath = f.getCanonicalPath(); } } else { readin = zip.getInputStream(entry); fos = new FileOutputStream(f); byte[] temp = new byte[BUFFER_SIZE]; int count = readin.read(temp); while (count != -1) { fos.write(temp, 0, count); count = readin.read(temp); } /*need to close the fos/readin as the fos/readin will be refer to another entry next time*/ fos.close(); readin.close(); } } } return rootfolderPath; } catch (Exception e) { log.error("Bad file format: " + spPath, e); return null; } finally { UpgradeUtils.close(readin, fos); zip.close(); } }