java 修改 jar 包文件内容的一个实例
                                                            生活随笔
收集整理的這篇文章主要介紹了
                                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 中的每一個文件夾 每一個文件 都是一個 jarEntryJarEntry 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();}} }轉載于:https://www.cnblogs.com/yang3wei/archive/2012/04/06/2739796.html
總結
以上是生活随笔為你收集整理的java 修改 jar 包文件内容的一个实例的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: 重金求购一份回合制手游源码
- 下一篇: Linux环境下压缩与解压命令大全
