开发这个小工具的初衷是为了修改工具 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波浪文字,一个利用Java处理字符的实例,可以设置运动方向参数,显示文本的字符数组,高速文本颜色,显示字体的 FontMetrics对象,得到Graphics实例,得到Image实例,填充颜色数组数据,初始化颜色数组。...
Java波浪文字,一个利用Java处理字符的实例,可以设置运动方向参数,显示文本的字符数组,高速文本颜色,显示字体的 FontMetrics对象,得到Graphics实例,得到Image实例,填充颜色数组数据,初始化颜色数组。...
Java波浪文字,一个利用Java处理字符的实例,可以设置运动方向参数,显示文本的字符数组,高速文本颜色,显示字体的 FontMetrics对象,得到Graphics实例,得到Image实例,填充颜色数组数据,初始化颜色数组。...
******************************************************** 作者:邓佑权 日期:2016年 功能:实现google的PageRank算法,带完整的...spark-assembly-1.6.1-hadoop2.6.0.jar 包文件太大,无法上传,请自行下载!
Java波浪文字,一个利用Java处理字符的实例,可以设置运动方向参数,显示文本的字符数组,高速文本颜色,显示字体的 FontMetrics对象,得到Graphics实例,得到Image实例,填充颜色数组数据,初始化颜色数组。...
Java波浪文字,一个利用Java处理字符的实例,可以设置运动方向参数,显示文本的字符数组,高速文本颜色,显示字体的 FontMetrics对象,得到Graphics实例,得到Image实例,填充颜色数组数据,初始化颜色数组。...
Java波浪文字,一个利用Java处理字符的实例,可以设置运动方向参数,显示文本的字符数组,高速文本颜色,显示字体的 FontMetrics对象,得到Graphics实例,得到Image实例,填充颜色数组数据,初始化颜色数组。...
这个是一个我修改过的fckeditor for jsp 的jar包的源代码,是fckeditor-2.3的,我修改了ConnectorServlet.java和SimpleUploaderServlet.java两个文件 我在这两个文件中都是加了一个静态变量encoding,private static...
java操作压缩文件和解压文件实例代码(经测试),把jar文件导入到项目里。源代码根据注释修改下路径就能用了
ftp4j是一个FTP客户端Java类库,实现了FTP客户端应具有的大部分功能文件(包括上传和下 载),浏览远程FTP服务器上的目录和文件,创建、删除、重命,移动远程目录和文件。ftp4j提供多种方式连接到远程FTP服务器包括...
ftp4j是一个FTP客户端Java类库,实现了FTP客户端应具有的大部分功能文件(包括上传和下 载),浏览远程FTP服务器上的目录和文件,创建、删除、重命,移动远程目录和文件。ftp4j提供多种方式连接到远程FTP服务器包括...
实例144 读取jar包文件 215 实例145 文件的加密/解密操作 217 实例146 复制图片 219 实例147 随机读写Java类文件 221 第3篇 Java面向对象编程 第8章 面向对象(教学视频:72分钟) 226 8.1 类 226 实例148 简单的...
数字证书:从文件中读取数字证书,生成文件输入流,输入文件为c:/mycert.cer,获取一个处理X.509证书的证书工厂…… Java+ajax写的登录实例 1个目标文件 内容索引:Java源码,初学实例,ajax,登录 一个Java+ajax写的...
ftp4j是一个FTP客户端Java类库,实现了FTP客户端应具有的大部分功能文件(包括上传和下 载),浏览远程FTP服务器上的目录和文件,创建、删除、重命,移动远程目录和文件。ftp4j提供多种方式连接到远程FTP服务器包括...
ftp4j是一个FTP客户端Java类库,实现了FTP客户端应具有的大部分功能文件(包括上传和下 载),浏览远程FTP服务器上的目录和文件,创建、删除、重命,移动远程目录和文件。ftp4j提供多种方式连接到远程FTP服务器包括...
ftp4j是一个FTP客户端Java类库,实现了FTP客户端应具有的大部分功能文件(包括上传和下 载),浏览远程FTP服务器上的目录和文件,创建、删除、重命,移动远程目录和文件。ftp4j提供多种方式连接到远程FTP服务器包括...
ftp4j是一个FTP客户端Java类库,实现了FTP客户端应具有的大部分功能文件(包括上传和下 载),浏览远程FTP服务器上的目录和文件,创建、删除、重命,移动远程目录和文件。ftp4j提供多种方式连接到远程FTP服务器包括...
ftp4j是一个FTP客户端Java类库,实现了FTP客户端应具有的大部分功能文件(包括上传和下 载),浏览远程FTP服务器上的目录和文件,创建、删除、重命,移动远程目录和文件。ftp4j提供多种方式连接到远程FTP服务器包括...
ftp4j是一个FTP客户端Java类库,实现了FTP客户端应具有的大部分功能文件(包括上传和下 载),浏览远程FTP服务器上的目录和文件,创建、删除、重命,移动远程目录和文件。ftp4j提供多种方式连接到远程FTP服务器包括...