需求背景:写了一个实时读取日志文件以及监控的小程序,打包成了Jar包可执行文件,通过我们的web主系统上传到各个服务器,然后调用ssh命令执行。每次上传前都要通过解压缩软件修改或者替换里面的配置文件,这样感觉有点麻烦,就想办法能不能通过程序动态生成配置文件,然后修改或者替换掉Jar包里的配置文件,最后再上传到各个服务器去执行。

实现历程:刚开始看了大量文章,整理出来了一个操作Jar包的工具类,用工具类里面的方法去修改一个30M左右的Jar包文件时,发现耗时竟然要7秒,而且修改Jar文件的方法确实有点复杂(这个可能需要开发JDK的专业人士提供简单、高效的方法了),果断忍受不了,然后想能不能通过其他的方法来实现。想到了一个方案,就是不通过java去修改Jar里的文件,而是用linux的Jar命令(当然也是通过java去调用linux命令),先解压缩jar包,然后将动态生成的配置文件替换解压缩包里的配置文件,最后再将目录压缩成Jar文件。经过测试,这样大概需要4秒的时间,确实快了不少。想了很久也没有想到其他更好的办法,正打算实施的时候,看到了这条命令:jar uf test.jar manifest.mf  -u 更新已存在的 JAR 文件包 (添加文件到 JAR 文件包中)  -f 指定 JAR 文件名;瞬间来了灵感,直接调用这条命令不就OK了!通过这条命令几秒钟就轻轻松松搞定了,简直是山穷水尽疑无路,柳暗花明又一村。

下面是我整理的操作Jar包的工具类(已经通过测试,可以拿去直接用),包括读取Jar包的文件内容,遍历 Jar包,修改 Jar包文件内容等操作,供大家参考。

packagecom.agent.util;importjava.io.BufferedReader;importjava.io.ByteArrayOutputStream;importjava.io.FileNotFoundException;importjava.io.FileOutputStream;importjava.io.IOException;importjava.io.InputStream;importjava.io.InputStreamReader;importjava.util.Enumeration;importjava.util.Iterator;importjava.util.Map;importjava.util.Set;importjava.util.TreeMap;importjava.util.jar.JarEntry;importjava.util.jar.JarFile;importjava.util.jar.JarOutputStream;public classJarUtil {/*** 读取jar包所有的文件内容,显示JAR文件内容列表

*@paramjarFileName

*@throwsIOException*/

public static void readJARList(String jarFilePath) throwsIOException {//创建JAR文件对象

JarFile jarFile = newJarFile(jarFilePath);//枚举获得JAR文件内的实体,即相对路径

Enumeration en =jarFile.entries();

System.out.println("文件名\t文件大小\t压缩后的大小");//遍历显示JAR文件中的内容信息

while(en.hasMoreElements()) {//调用方法显示内容

process(en.nextElement());

}

}//显示对象信息

private static voidprocess(Object obj) {//对象转化成Jar对象

JarEntry entry =(JarEntry) obj;//文件名称

String name =entry.getName();//文件大小

long size =entry.getSize();//压缩后的大小

long compressedSize =entry.getCompressedSize();

System.out.println(name+ "\t" + size + "\t" +compressedSize);

}/*** 读取jar包里面指定文件的内容

*@paramjarFileName jar包文件路径

*@paramfileName 文件名

*@throwsIOException*/

public static void readJarFile(String jarFilePath,String fileName) throwsIOException{

JarFile jarFile= newJarFile(jarFilePath);

JarEntry entry=jarFile.getJarEntry(fileName);

InputStream input=jarFile.getInputStream(entry);

readFile(input);

jarFile.close();

}public static void readFile(InputStream input) throwsIOException{

InputStreamReader in= newInputStreamReader(input);

BufferedReader reader= newBufferedReader(in);

String line ;while((line = reader.readLine())!=null){

System.out.println(line);

}

reader.close();

}/*** 读取流

*

*@paraminStream

*@return字节数组

*@throwsException*/

public static byte[] readStream(InputStream inStream) throwsException {

ByteArrayOutputStream outSteam= newByteArrayOutputStream();byte[] buffer = new byte[1024];int len = -1;while ((len = inStream.read(buffer)) != -1) {

outSteam.write(buffer,0, len);

}

outSteam.close();

inStream.close();returnoutSteam.toByteArray();

}/*** 修改Jar包里的文件或者添加文件

*@paramjarFile jar包路径

*@paramentryName 要写的文件名

*@paramdata 文件内容

*@throwsException*/

public static void writeJarFile(String jarFilePath,String entryName,byte[] data) throwsException{//1、首先将原Jar包里的所有内容读取到内存里,用TreeMap保存

JarFile jarFile = newJarFile(jarFilePath);//可以保持排列的顺序,所以用TreeMap 而不用HashMap

TreeMap tm = newTreeMap();

Enumeration es=jarFile.entries();while(es.hasMoreElements()){

JarEntry je=(JarEntry)es.nextElement();byte[] b =readStream(jarFile.getInputStream(je));

tm.put(je.getName(),b);

}

JarOutputStream jos= new JarOutputStream(newFileOutputStream(jarFilePath));

Iterator it=tm.entrySet().iterator();boolean has = false;//2、将TreeMap重新写到原jar里,如果TreeMap里已经有entryName文件那么覆盖,否则在最后添加

while(it.hasNext()){

Map.Entry item=(Map.Entry) it.next();

String name=(String)item.getKey();

JarEntry entry= newJarEntry(name);

jos.putNextEntry(entry);byte[] temp ;if(name.equals(entryName)){//覆盖

temp =data;

has= true;

}else{

temp= (byte[])item.getValue();

}

jos.write(temp,0, temp.length);

}if(!has){//最后添加

JarEntry newEntry = newJarEntry(entryName);

jos.putNextEntry(newEntry);

jos.write(data,0, data.length);

}

jos.finish();

jos.close();

}/*** 测试案例

*@paramargs

*@throwsException*/

public static void main(String args[]) throwsException{// readJarFile("D:\\esjavaclient-0.0.1-SNAPSHOT.jar","es-info.properties");

String data= "helloBabydsafsadfasdfsdafsdgasdgweqtqwegtqwfwefasdfasfadfasf";long start =System.currentTimeMillis();

writeJarFile("D:\\esjavaclient-0.0.1-SNAPSHOT.jar","es-info.properties",data.getBytes());long end =System.currentTimeMillis();

System.out.println(end-start);

readJarFile("D:\\esjavaclient-0.0.1-SNAPSHOT.jar","es-info.properties");

}

}

View Code

上面有个测试案例,测试读取其中一个配置文件,然后修改这个文件,最后再读取出来。 一个30M左右的Jar包文件耗时7秒多,实在忍受不了。网上找了很多文章,同时看了Zip相关的源码,也木有找到可以直接修改Jar包文件内容的方法。 最后只能另辟蹊径,找到了一个执行效率非常快的方法。

关于工具类没有删除文件的方法,大家根据修改的方法稍微改造一下即可。

工具类参考的博客:

如何快速修改Jar包里的文件内容:

贴出来我巧妙实现的代码:(如果不知道Java 如何调用linux命令的同学,请先补习一下这方面的知识)

String cmd = "jar uf esjavaclient-0.0.1-SNAPSHOT.jar config.properties";

String[] cmds = {"/bin/sh","-c",cmd};

Process pro;

try{

pro =Runtime.getRuntime().exec(cmds);

pro.waitFor();

InputStream in =pro.getInputStream();

BufferedReader read = new BufferedReader(newInputStreamReader(in));

String line = null;

while((line = read.readLine())!=null){

System.out.println(line);

}

} catch(Exception e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

通过执行这条条命令,就可以很快将我们生成的配置文件config.properties覆盖掉Jar里的文件,从而达到修改的目的。

总结:如果Jar包里的文件不大的话,完全可以用工具类提供的方法去操作Jar包。比较大的话,修改Jar包的方法,推荐用我那个巧妙的方法。

最后:给开发JDK的专业人士提点建议,关于操作压缩包这方面的API还不够强大,希望后续可以完善一下

java -uf_Java如何快速修改Jar包里的文件内容相关推荐

  1. 打包部署后无法读取jar包里的文件(实测可行,Java中读取jar包中的文件)

    打包部署后无法读取jar包里的文件 Java中读取jar包中的文件 linux中无法读取jar包中的内容(windows可以的!),如何解决 一.背景 项目中免不了需要读取文件,如果文件用绝对路径读取 ...

  2. java package 目录_修改jar包package目录结构操作方法

    本文将为您描述修改jar包package目录结构操作方法,具体操作过程: 开发中会遇到用第三方的jar包,有时候会出现不同的jar包,包名一致的情况,这就会引发运行时异常,找不到相应的jar包. 这种 ...

  3. 快速修改jar包源码

    本人在学习javaweb过程中使用之前自己写好并打包出来的jar包,但在后续使用过程中发现源码需要进行补充,在网络上搜了很多修改jar包的方法,现在记录一下一个我觉得比较方便的办法. 第一步,打开你要 ...

  4. java class修改_【原创】Java基础之简单修改jar包中的class

    有时需要修改很多jar(假设这些jar都位于lib目录)中其中一个jar中的某一个类,而且又没有原始代码或ide,这时最简单的方式是: 1 进入lib目录 #cd lib#ls test.jar de ...

  5. jd+jbe修改jar包中class文件

    有时候从网上下的java demo中,有的是发布后的环境,所以只有jar包信息,没有对应的源码,我们要把其中的信息修改下,所以就需要我们本文中提到的直接修改java class信息.参考网上资料好,赶 ...

  6. 修改jar包中class文件

    需求:银行跑批任务执行时要调用行方自己的短信平台给科技部人员发送短信,行方提供一个jar文件,通过shell脚本传参调用即可. 问题点:shell脚本调用jar包没太大问题,关键在于,需要在jar包中 ...

  7. 怎么修改jar包的yml文件_电脑怎么批量修改文件名

    大家好,今天分享一篇来源小白一键重装网(xiaobaixitong.com)关于解答:电脑怎么批量修改文件名. 电脑怎么批量修改文件名呢?很多小伙伴喜欢手机自拍,然后把自拍照片存储到电脑里,需要给照片 ...

  8. 直接修改Jar包class文件方法

    前言 同事有一天向我求助,需求是这样的:需要修改一个jar中的某一个class文件的代码,没有源码.[其实就是想破解一个插件的限制] 可能的解决思路: (1)class文件反编译成java文件,修改完 ...

  9. 替换jar包或者war包里的文件

    背景 一般情况下,我们通过某种工具(比如Maven)生成 xxx.jar 或者 xxx.war 文件.有时希望修改里面的一个文件,比如 xxx.class 文件,又或者是一个配置文件,但又不想重新bu ...

最新文章

  1. 【C++】重载运算符(一)
  2. Windows 7无法使用Telnet命令
  3. SPOJ Supernumbers in a permutation(LIS)
  4. 多线程必须用到的线程池(什么时候用多线程)
  5. 前缀 中缀 后缀表达式
  6. 高可用与负载均衡(7)之聊聊Lvs-DR+Keepalived的解决方案
  7. JQ学习(三)-ajax
  8. visual studio报错:error C4996: ‘scanf‘
  9. python zipfile_python zipfile模块
  10. 挣钱难,做老板不易,特别是种植老板
  11. .net中调用windows performance记录性能信息
  12. 19-background
  13. 高数_第2章多元函数微分学__偏导数的几何应用_空间曲线的切线与法平面
  14. 设置用户计算机的ip地址,电脑动态IP地址怎么设置
  15. 怎么录制游戏视频,哪个电脑录屏软件好用?
  16. 三安集成长沙碳化硅制造基地下半年启动投产;龙芯中科正式发布完全自主指令集架构 | 美通企业日报...
  17. 联创机房管理系统重连服务器失败,联创机房管理系统在CAD实验室应用探析.doc...
  18. RecyclerView(侧滑删除)和下载文件
  19. KK 给年轻人的99条建议
  20. 稀疏数组的创建与读写文件操作

热门文章

  1. math python 向上取整_Python成为专业人士笔记-各数学运算操作深度剖析
  2. python字符串为什么不能修改_为什么在Python(\n)中更改字符串中的行不起作用?...
  3. hog函数的用法 python_Python常见内置函数用法(三)
  4. 中小学生学python_《中小学生Python编程入门指南》 附录一
  5. 用S-函数编写Simulink中的正弦模块
  6. 【每日SQL打卡】​​​​​​​​​​​​​​​DAY 12丨销售分析 III【难度简单】
  7. 被讨厌的勇气--总结
  8. matlab m序列,m序列(M序列与m序列区别)
  9. mysql load data infile 导入数据 某一列 空_Sql数据挑战赛amp;网络销售案例分析
  10. java中no1_Java程序设计实验(NO.1).doc