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

  

Java中,jar (Java Archive) 文件是一种用于打包Java类、资源和其他文件的归档格式。如果你想从已经存在的jar文件中移除特定的一个文件,通常需要通过jar命令行工具或者第三方库如Apache Commons Compress来操作。以下是基本步骤: 1. **使用`jar`命令**: 使用`java.util.jar.JarEntry`类配合`java.util.jar.JarFile`,你可以读取jar文件并删除指定的条目。首先,你需要创建一个`JarOutputStream`,然后遍历`JarFile`中的条目,选择要移除的那个,最后关闭流。 ```java import java.io.*; import java.util.jar.*; public void removeFileFromJar(String jarPath, String fileName) throws IOException { JarFile jar = new JarFile(jarPath); try { JarEntry entry = jar.getEntry(fileName); if (entry != null) { // 检查文件是否存在于jarjar.removeEntry(entry.getName()); } } finally { jar.close(); } } ``` 2. **使用`commons-compress`库** (如果需要处理大jar或性能优化): Apache Commons Compress库提供了一个更方便的方法来读写jar文件,包括添加、更新和删除条目。首先,你需要添加依赖,然后可以使用`ZipArchiveInputStream`和`ZipArchiveOutputStream`。 ```java import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream; public void removeFileFromJarWithCommonsCompress(String jarPath, String fileName) throws IOException { ZipArchiveOutputStream zipOut = new ZipArchiveOutputStream(new FileOutputStream(jarPath + ".updated")); try (ZipArchiveInputStream zipIn = new ZipArchiveInputStream(new FileInputStream(jarPath))) { ZipArchiveEntry entry = zipIn.getNextEntry(); while (entry != null) { if (!entry.getName().equals(fileName)) { // 避免删除目标文件 zipOut.putNextEntry(entry); byte[] buffer = new byte[1024]; int length; while ((length = zipIn.read(buffer)) > 0) { zipOut.write(buffer, 0, length); } } zipIn.closeEntry(); entry = zipIn.getNextEntry(); } } zipOut.finish(); zipOut.close(); Files.move(Paths.get(jarPath), Paths.get(jarPath + ".updated"), StandardCopyOption.REPLACE_EXISTING); // 更新原jar文件 } ``` 记得在实际操作前备份原始jar文件,并检查权限。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值