`
java-mans
  • 浏览: 11632705 次
文章分类
社区版块
存档分类
最新评论

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


分享到:
评论

相关推荐

    java的workbook类的jar包

    在Java中,当你需要与Excel交互时,首先需要创建或加载一个`Workbook`实例。如果你要创建一个新的Excel文件,可以使用`WorkbookFactory.create()`方法,并指定你想要的格式(如`.xlsx`或`.xls`)。如果是要读取已有...

    Java连接opc所需的jar包,以及Java实现opc server客户端的源码.zip

    `jeasyopc`是一个开源的Java OPC库,它提供了简单易用的API来与OPC服务器进行通信。在提供的压缩包中,`jeasyopc-2.3.2`很可能就是这个库的版本,包含了所需的JAR文件。这些JAR文件包括了核心的OPC连接组件,可能...

    javaParser 包 javaparser-core-3.6.16.jar

    JavaParser 是一个强大的开源库,专门用于解析、分析和修改 Java 源代码。这个工具在 Java 开发中尤其有用,因为它允许程序员在运行时或构建过程中动态处理和操作 Java 代码。`javaparser-core-3.6.16.jar` 文件是 ...

    泛微E-cology 二次开发Java Jar包

    本压缩包中的"泛微E-cology 二次开发JAVA jar包",重点在于"jar"文件,这是一种Java平台下的可执行文件格式,用于打包类库、资源文件等,便于Java程序调用。E8版本表示这是泛微E-cology的一个特定版本,可能包含了...

    Thinking in Java专用jar包-第4版(Java编程思想专用jar包)

    `TinkingInJava.jar`可能是包含《Thinking in Java》书中所有实例代码的jar文件,用户可以直接引用它来运行书中提供的程序。而`typeinfo-pets.jar`可能包含与类型信息和宠物类相关的示例,这可能是为了展示Java的...

    java读取ini文件jar

    Java语言在处理各种类型的文件...这个“java读取ini文件jar”压缩包的实例为你提供了一个起点,帮助你在项目中实现Ini文件的读取功能。根据实际情况调整代码,你可以读取和修改Ini文件中的任何数据,满足你的应用需求。

    java excel解析jar包 poi

    本压缩包包含的"poi"文件很可能是Apache POI的特定版本或者一个简化版,用于简化Java开发者的工作流程。 Apache POI提供了一组API,允许开发人员在Java应用程序中创建、更新和读取Excel(XLS和XLSX)、Word(DOC和...

    java excel HSSFWorkbook的jar包

    Apache POI是一个开源的Java API,允许开发人员创建、修改和显示Microsoft Office文档。 在Java中使用HSSFWorkbook,我们可以实现以下功能: 1. **读取Excel文件**:HSSFWorkbook对象可以用来打开一个.xls文件,...

    java源码包---java 源码 大量 实例

     Java波浪文字,一个利用Java处理字符的实例,可以设置运动方向参数,显示文本的字符数组,高速文本颜色,显示字体的 FontMetrics对象,得到Graphics实例,得到Image实例,填充颜色数组数据,初始化颜色数组。...

    自己用的一些JAVA工具类做成的jar包

    根据给出的文件名“MyUtils”,我们可以推断这个JAR包的核心类库名为"MyUtils",它很可能是一个包含各种工具方法的Java类。在Java编程中,工具类通常以静态方法为主,不包含实例化对象,方便直接调用。MyUtils类可能...

    用反射解析jar文件并执行里面Java代码

    本篇文章将深入探讨如何使用反射来解析jar文件并执行其中的Java代码。 首先,让我们理解jar文件的结构。Java Archive (JAR) 文件是Java平台上的归档文件格式,通常用于存储多个类文件、资源文件和其他元数据。这些...

    selenium-java-3.3.1 jar包

    【标题】"selenium-java-3.3.1 jar包" 涉及的主要知识点是 Selenium,这是一个自动化测试工具,广泛用于Web应用程序的自动化测试。Selenium 支持多种编程语言,包括Java,使得测试脚本可以使用Java编写。3.3.1是该...

    cassandra数据库 java链接 jar包

    在提供的压缩包“cassandra java链接应用包”中,可能包含了一个预打包的环境,集成了所需的JAR包和其他相关依赖。这使得开发者可以快速开始与Cassandra的交互,而无需单独下载和管理每个依赖项。在使用这个压缩包时...

    java poi xhtmloptions 所以jar包

    Java POI库是Apache软件基金会开发的一个开源项目,主要用于处理Microsoft Office格式的文件,如Word(.doc/.docx)、Excel(.xls/.xlsx)和PowerPoint(.ppt/.pptx)。在Java程序中,我们可以使用POI库来读取、创建...

    java发送邮件jar包和demo

    1. **activation.jar**:这是JavaBeans Activation Framework (JAF)的JAR文件,用于处理和识别不同的MIME类型,是Java发送电子邮件所必需的库。它提供了对标准MIME类型的自动识别和处理,使得开发者可以方便地处理...

    SAP Business One的二次开发java的jar包

    在描述中提到的"java的jar包",指的是Java Archive (JAR) 文件,它是Java平台中用于集合多个类文件、相关的元数据和资源文件的容器。在SAP Business One的二次开发中,这些JAR文件通常包含了SAP提供的开发库,如SAP ...

    jxl操作excel实例,jxl jar包下载

    在这个例子中,我们将创建一个名为`Test.java`的文件,用于演示如何使用`jxl`库。 ```java import jxl.*; import jxl.write.*; public class Test { public static void main(String[] args) { // 读取Excel文件...

    java使用Json所需要导入的所有jar包

    为了在Java项目中使用这些库,你需要将这些jar文件添加到项目的类路径(classpath)中。如果你使用的是Maven或Gradle,可以通过在`pom.xml`或`build.gradle`文件中添加对应的依赖来实现。 总的来说,这些jar包覆盖...

    微软云Blob存储java开发所需的jar包

    Java Archive (JAR) 文件是一种归档格式,用于将多个类文件、资源文件和其他元数据打包成一个单一的文件,便于分发和运行。在微软云Blob存储的Java开发中,这些jar包包含了必要的API和库,使开发者能够与Azure Blob...

    excel文件导入jar包

    `jxl.jar` 是一个用于读写Excel文件的Java库,它允许开发者在Java程序中创建、修改和读取Excel工作簿。JExcelApi支持Biff8格式,这是Microsoft Excel 97及以后版本使用的文件格式。通过这个库,你可以执行以下操作:...

Global site tag (gtag.js) - Google Analytics