java 修改 jar 包文件内容的一个实例

开发这个小工具的初衷是为了修改工具 jar 包中的配置文件

本来打算将这个功能集成到 工具 jar 包自身

但是这里貌似有点儿问题,因为该 jar 包文件当前正在被 java 虚拟机使用,所以无法对其进行修改操作~

这里我有点儿疑惑,难道不是将 jar 包整个加载到内存中去了么?

为什么磁盘上的物理文件还是被牢牢锁定?mac上是这样,windows里面也是这样,应该有点儿蹊跷,不深究了~

本示例主要包含了以下知识点:

1。遍历 jar 文件中的所有文件(jar包实际上就是zip压缩包,没什么神奇的)

2。就像读取磁盘中的其他文件一样,对jar执行 读入和写出操作

3。将 jar文件中的某个文件读到 swing的 jTextArea 里面,在退出的时候将修改过的文字覆盖回原文件

4。将InputStream 安全的转换为 byte[] 数组

5。拖拽取得文件的完整路径

下面直接上代码实例:

package org.bruce.vertices.extra; import java.awt.Toolkit; import java.awt.datatransfer.DataFlavor; import java.awt.dnd.DnDConstants; import java.awt.dnd.DropTarget; import java.awt.dnd.DropTargetAdapter; import java.awt.dnd.DropTargetDropEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.Enumeration; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.jar.JarOutputStream; import java.util.zip.ZipEntry; import javax.swing.JFrame; import javax.swing.JOptionPane; import javax.swing.JScrollBar; import javax.swing.JScrollPane; import javax.swing.JTextArea; /** * @author Bruce Yang * PS:本示例专门用于编辑我自己制作的一个 jar 文件的属性文件, * 是不具备通用性的。不过源码既然放出,变得适应各种不同的需求,自然是不存在什么难题~ * 为了方便地提供最基本的适应需求,主要将 configPath 修改为各自 jar包中 配置文件的 classPath 即可~ * 一言以蔽之: * 这个工具主要起到了快捷修改jar文件中某个配置文件的作用~ * 遗憾的是,还有一些需求我没能完成,诸如怎么将JTextArea中属性文件的内容修改的和elcipse中打开属性文件一样, * 那样的话,‘=’,‘true’,‘false’,整数等值具备了不同高亮颜色的话,看起来就舒服多了~ * 各位有兴趣可以试试,据我目前所知,JTextPane貌似更加适合做这个功能,但是有些小细节我不明了。。。 * 如有对这个同样感兴趣且扩展出上述“高亮”功能的大侠,还请给我邮一份,不甚感激! * 在下邮箱:bestfighter@yeah.net */ public class JarCfgEditor extends JFrame { private static final long serialVersionUID = -7044615012246731094L; public String configPath = "org/bruce/vertices/resources/DefaultCfg.properties"; public static final int CONSOLE_DIALOG_WIDTH = 500; public static final int CONSOLE_DIALOG_HEIGHT = 400; private JScrollPane jsp; private JTextArea jta; private File original; private void initMemberVariables() { jta = new JTextArea(); jsp = new JScrollPane(); } public JarCfgEditor() { super(); this.initMemberVariables(); this.setSize(500, 400); jsp.setViewportView(jta); this.add(jsp); JScrollBar jsb = jsp.getVerticalScrollBar(); jsb.setValue(jsb.getMaximum()); int screenWidth = Toolkit.getDefaultToolkit().getScreenSize().width; int screenHeight = Toolkit.getDefaultToolkit().getScreenSize().height; this.setLocation((screenWidth-CONSOLE_DIALOG_WIDTH)/2, (screenHeight-CONSOLE_DIALOG_HEIGHT)/2); /** 关闭的时候将修改过的属性覆盖到 jar 里面的属性配置文件~ */ this.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent arg0) { if(original != null) { write2JarFile(); } System.exit(0); } }); new DropTarget(jta, DnDConstants.ACTION_COPY_OR_MOVE, new MyDropTargetListener(this)); this.setTitle("CfgViewer0.1"); this.setVisible(true); } /** * 写入jar文件的话会将 jar文件原来的内容统统抹掉!!切记!!~ */ private void write2JarFile() { String originalPath = original.getAbsolutePath(); /** 创建一个临时文件来做暂存,待一切操作完毕之后会将该文件重命名为原文件的名称(原文件会被删除掉)~ */ String tempPath = originalPath.substring(0, originalPath.length()-4) + "_temp.jar"; System.out.println(tempPath); JarFile originalJar = null; try { originalJar = new JarFile(originalPath); } catch (IOException e1) { e1.printStackTrace(); } List<JarEntry> lists = new LinkedList<JarEntry>(); for(Enumeration<JarEntry> entrys = originalJar.entries(); entrys.hasMoreElements();) { JarEntry jarEntry = entrys.nextElement(); // System.out.println(jarEntry.getName()); lists.add(jarEntry); } // 定义一个 jaroutputstream 流 File handled = new File(tempPath); JarOutputStream jos = null; try { FileOutputStream fos = new FileOutputStream(handled); jos = new JarOutputStream(fos); /** * 将源文件中的内容复制过来~ * 可以利用循环将一个文件夹中的文件都写入jar包中 其实很简单 */ for(JarEntry je : lists) { // jar 中的每一个文件夹 每一个文件 都是一个 jarEntry JarEntry newEntry = new JarEntry(je.getName()); // newEntry.setComment(je.getComment()); // newEntry.setCompressedSize(je.getCompressedSize()); // newEntry.setCrc(je.getCrc()); // newEntry.setExtra(je.getExtra()); // newEntry.setMethod(je.getMethod()); // newEntry.setTime(je.getTime()); // System.out.println(je.getAttributes()); /** 这句代码有问题,会导致将jar包重命名为zip包之后无法解压缩~ */ // newEntry.setSize(je.getSize()); // 表示将该entry写入jar文件中 也就是创建该文件夹和文件 jos.putNextEntry(newEntry); /** 如果当前已经处理到属性文件了,那么将在 JTextArea 中编辑过的文本写入到该属性文件~ */ if(je.getName().equals(configPath)) { jos.write(jta.getText().getBytes()); continue; } InputStream is = originalJar.getInputStream(je); byte[] bytes = inputStream2byteArray(is); is.close(); // 然后就是往entry中的jj.txt文件中写入内容 jos.write(bytes); } // 最后不能忘记关闭流 jos.close(); fos.close(); /** 删除原始文件,将新生成的文件重命名为原始文件的名称~ */ original.delete(); handled.renameTo(new File(originalPath)); } catch (Exception e) { e.printStackTrace(); } } /** * InputStream 转 byte[]~ * @param is * @return */ public static byte[] inputStream2byteArray(InputStream is) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); int i; try { while((i = is.read()) != -1) { baos.write(i); } baos.close(); } catch (IOException e) { e.printStackTrace(); } byte[] bytes = baos.toByteArray(); return bytes; } /** getters && setters~ */ public JTextArea getJta() { return jta; } public void setJta(JTextArea jta) { this.jta = jta; } public File getJarFile() { return original; } public void setJarFile(File jarFile) { this.original = jarFile; } /** * 主方法~ * @param args */ public static void main(String[] args) { new JarCfgEditor(); } } /** * @author Bruce Yang * 拖拽监听~ */ class MyDropTargetListener extends DropTargetAdapter { private JarCfgEditor jce; public MyDropTargetListener(JarCfgEditor jce) { this.jce = jce; } @Override @SuppressWarnings("unchecked") public void drop(DropTargetDropEvent event) { if (event.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) { event.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE); DataFlavor df = DataFlavor.javaFileListFlavor; List<File> list = null; try { list = (List<File>)(event.getTransferable().getTransferData(df)); } catch (Exception e) { e.printStackTrace(); } Iterator<File> iterator = list.iterator(); while (iterator.hasNext()) { File file = iterator.next(); if(file.exists() && file.isFile()) { String filePath = file.getAbsolutePath(); if(filePath == null || filePath.equals("")) { System.out.println("文件名为 null 或为 \"\"~"); break; } if(!filePath.contains("GetVerticesMVC") || !filePath.endsWith(".jar")) { String str = "此工具专门为 GetVerticesMVC 设计,不通用!! 请注意!!"; JOptionPane.showMessageDialog(null, str); break; } System.out.println("jarFilePath=" + filePath); jce.setJarFile(file); JarFile jarFile = null; try { jarFile = new JarFile(filePath); ZipEntry entry = jarFile.getEntry(jce.configPath); if(entry == null) { System.out.println(jce.configPath+"路径所代表的文件不存在!读取失败~"); // 安全起见,将 jarFile 置为 null,这样在关闭窗口的时候将不会执行收尾操作~ jce.setJarFile(null); break; } //获取到inputstream了 就相当简单了 InputStream is = jarFile.getInputStream(entry); byte[] bytes = JarCfgEditor.inputStream2byteArray(is); String cfgStr = new String(bytes); jce.getJta().setText(cfgStr); } catch (IOException e) { e.printStackTrace(); } } // 一次只能处理一个,要避免处理多个的情况,因此 break 跳出~ break; } event.dropComplete(true); } else { event.rejectDrop(); } } }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值