使用原生Java程式碼生成可執行Jar包

Mr.Johness發表於2014-03-02

  最近想做一個功能,就是把我們編譯後的位元組碼及其資原始檔打包成一個可執行的jar包,在裝有jre的機器上雙擊就能執行。

  首先是我們需要選擇哪些位元組碼和檔案需要打包到檔案中,這個我們用JFileChooser來做,讓使用者選擇,我做了一個窗體來讓使用者選擇。

  效果如下:

  

  我們讓瀏覽檔案系統,並選擇需要打包的資料夾,然後計算出可以作為啟動類的檔案,通過下方的下拉讓使用者選擇。

  生成檔案路徑在確認按鈕點選後彈出檔案儲存框讓使用者選擇就好(也可以彈出輸入框)。

  程式碼如下:

  Main

 1 package org.coderecord.commons.ejarmaker;
 2 
 3 import java.awt.EventQueue;
 4 
 5 import javax.swing.UIManager;
 6 import javax.swing.UnsupportedLookAndFeelException;
 7 
 8 public class Main {
 9 
10     public static void main(String[] args) {
11         try {
12             UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
13         } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException e) {
14             e.printStackTrace();
15         }
16         EventQueue.invokeLater(new Runnable() {
17             
18             @Override
19             public void run() {
20                 new FrmMain().setVisible(true);
21             }
22         });
23     }
24 
25 }
Main

  FrmMain(只是介面程式碼,業務程式碼最後貼出)

  1 package org.coderecord.commons.ejarmaker;
  2 
  3 import java.awt.Toolkit;
  4 import java.awt.event.ActionEvent;
  5 import java.awt.event.ActionListener;
  6 import java.io.File;
  7 import java.util.ArrayList;
  8 import java.util.List;
  9 
 10 import javax.swing.JButton;
 11 import javax.swing.JComboBox;
 12 import javax.swing.JFileChooser;
 13 import javax.swing.JFrame;
 14 import javax.swing.JLabel;
 15 import javax.swing.JScrollPane;
 16 import javax.swing.JTextArea;
 17 import javax.swing.filechooser.FileFilter;
 18 
 19 public class FrmMain extends JFrame implements ActionListener {
 20 
 21     private static final long serialVersionUID = 2016913328739206536L;
 22     // 選擇的檔案(使用者在檔案選擇器中選擇的)
 23     private List<File> userSelectedFiles = new ArrayList<>();
 24     // 我們經過分析得到的最終會被打包的檔案
 25     private List<File> finalFiles = new ArrayList<>();
 26     
 27     public FrmMain() {
 28         setSize(480, 320);
 29         setResizable(false);
 30         setLocationRelativeTo(null);
 31         setTitle("通用可執行Jar包生成工具");
 32         setDefaultCloseOperation(EXIT_ON_CLOSE);
 33         setLayout(null);
 34         // 在執行時獲取資原始檔的方式,一定是使用Class.getResource方式
 35         // 在jar包中這種方式也行得通
 36         // ‘/’代表根路徑
 37         setIconImage(Toolkit.getDefaultToolkit().getImage(FrmMain.class.getResource("/resources/icon.png")));
 38         initComponents();
 39     }
 40     
 41     // 初始化元件
 42     private void initComponents() {
 43         // 提示
 44         lblTip = new JLabel("選擇需要打包的檔案並設定啟動類");
 45         lblTip.setLocation(20, 10);
 46         lblTip.setSize(350, 20);
 47         add(lblTip);
 48         
 49         // 瀏覽按鈕
 50         btnBrowser = new JButton("瀏 覽");
 51         btnBrowser.setLocation(380, 10);
 52         btnBrowser.setSize(80, 24);
 53         btnBrowser.addActionListener(this);
 54         add(btnBrowser);
 55         
 56         // 展示已選擇檔案
 57         JScrollPane jspFiles = new JScrollPane();
 58         txtFiles = new JTextArea();
 59         txtFiles.setEditable(false);
 60         jspFiles.setSize(440, 160);
 61         jspFiles.setLocation(20, 40);
 62         txtFiles.setSize(440, 201600);
 63         txtFiles.setLocation(20, 40);
 64         txtFiles.setFocusable(false);
 65         jspFiles.setViewportView(txtFiles);
 66         add(jspFiles);
 67         
 68         // 選擇啟動類
 69         cobMainClass = new JComboBox<>();
 70         cobMainClass.setSize(440, 30);
 71         cobMainClass.setLocation(20, 210);
 72         add(cobMainClass);
 73         
 74         // 清除已選
 75         btnCls = new JButton("重 選");
 76         btnCls.setLocation(20, 250);
 77         btnCls.setSize(80, 24);
 78         btnCls.addActionListener(this);
 79         add(btnCls);
 80 
 81         // 確認按鈕
 82         btnConfirm = new JButton("確認");
 83         btnConfirm.setSize(80, 24);
 84         btnConfirm.setLocation(380, 250);
 85         btnConfirm.addActionListener(this);
 86         add(btnConfirm);
 87         
 88         // 檔案選擇器
 89         jfcSelect = new JFileChooser();
 90         // 可以選擇檔案和資料夾
 91         jfcSelect.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
 92         // 可以多選
 93         jfcSelect.setMultiSelectionEnabled(true);
 94         
 95         // 檔案儲存
 96         jfcSave = new JFileChooser();
 97         // 設定只接受以“.jar”結尾的檔案
 98         jfcSave.setAcceptAllFileFilterUsed(false);
 99         jfcSave.setFileFilter(new FileFilter() {
100             
101             @Override
102             public String getDescription() {
103                 return "可執行Jar";
104             }
105             
106             @Override
107             public boolean accept(File f) {
108                 return f.getName().endsWith(".jar");
109             }
110         });
111     }
112 
113     @Override
114     public void actionPerformed(ActionEvent e) {
115         
116     }
117     
118     private JLabel lblTip;
119     private JButton btnBrowser;
120     private JFileChooser jfcSelect;
121     private JTextArea txtFiles;
122     private JComboBox<String> cobMainClass;
123     private JButton btnCls;
124     private JButton btnConfirm;
125     private JFileChooser jfcSave;
126 }
FrmMain_UI

  然後開始業務部分,首先是選擇檔案,我們允許使用者選擇多個檔案和資料夾(甚至可以通過多次選擇來選擇不同碟符、路徑下的檔案和資料夾),在選擇後可能有重複的地方或兩次選擇後有包含的專案,我們要去除。

  我們為“瀏覽”按鈕事件新增處理,讓使用者選擇檔案並處理選中檔案:

  1 @Override
  2     public void actionPerformed(ActionEvent e) {
  3         if(e.getSource() == btnBrowser) {
  4             // 瀏覽
  5             int result = jfcSelect.showOpenDialog(this);
  6 
  7             // 選擇了檔案
  8             if(result == JFileChooser.APPROVE_OPTION) {
  9                 for(File file : jfcSelect.getSelectedFiles())
 10                     userSelectedFiles.add(file);
 11                 
 12                 // 整理選擇的檔案,去除重複項
 13                 removeDuplicateItems(userSelectedFiles);
 14                 
 15                 // 重新計算選中檔案
 16                 finalFiles.clear();
 17                 for(File file : userSelectedFiles)
 18                     addFileToList(file, finalFiles);
 19                 
 20                 // 計算檔案展示打包路徑及展示路徑
 21                 // 計算可啟動類路徑
 22                 // 展示到文字框中
 23                 cobMainClass.removeAllItems();
 24                 txtFiles.setText("");
 25                 File file,direc;
 26                 String filePath,direcPath;
 27                 Iterator<File> itd,itf;
 28                 for(itd = userSelectedFiles.iterator(); itd.hasNext();) {
 29                     direc = itd.next();
 30                     direcPath = direc.getAbsolutePath();
 31                     for(itf = finalFiles.iterator(); itf.hasNext();) {
 32                         file = itf.next();
 33                         filePath = file.getAbsolutePath();
 34                         if(filePath.equalsIgnoreCase(direcPath)) {
 35                             txtFiles.append(file.getName() + "\n");
 36                             filePaths.put(file.getName(), file);
 37                             //fileNames.put(file.getName(), file.getName().endsWith(".class")?file.getName().substring(0, file.getName().lastIndexOf('.')):file.getName());
 38                             if(file.getName().endsWith(".class"))
 39                                 cobMainClass.addItem(file.getName().endsWith(".class")?file.getName().substring(0, file.getName().lastIndexOf('.')):file.getName());
 40                             itf.remove();
 41                         } else if(filePath.startsWith(direcPath)) {
 42                             String nameTmp = filePath.substring(direcPath.lastIndexOf(File.separator) + 1).replace(File.separatorChar, '/'); 
 43                             filePaths.put(nameTmp, file);
 44                             txtFiles.append(nameTmp + "\n");
 45                             //fileNames.put(nameTmp, nameTmp.endsWith(".class")?nameTmp.substring(0, nameTmp.lastIndexOf('.')).replace('/', '.'):nameTmp);
 46                             if(nameTmp.endsWith(".class") && nameTmp.indexOf('$') == -1)
 47                                 cobMainClass.addItem(nameTmp.substring(0, nameTmp.lastIndexOf('.')).replace('/', '.'));
 48                             itf.remove();
 49                         }
 50                     }
 51                 }
 52             }
 53         }
 54     }
 55     
 56     // 新增檔案(非資料夾)到集合
 57     private void addFileToList(File file, List<File> fileArr) {
 58         if(file.isDirectory())
 59             for(File child : file.listFiles())
 60                 addFileToList(child, fileArr);
 61         else
 62             fileArr.add(file);
 63     }
 64     
 65     // 去除重複項
 66     private void removeDuplicateItems(List<File> fileArr) {
 67         // 去重複項
 68         Set<String> directories = new HashSet<>();
 69         Set<String> files = new HashSet<>();
 70         for(File file : fileArr)
 71             if(file.isDirectory())
 72                 directories.add(file.getAbsolutePath());
 73             else
 74                 files.add(file.getAbsolutePath());
 75         //去包含項(先去資料夾再去檔案應該更好)
 76         String fpath,dpath;
 77         for(Iterator<String> itf = files.iterator(); itf.hasNext();) {
 78             fpath = itf.next();
 79             for(Iterator<String> itd = directories.iterator(); itd.hasNext();) {
 80                 dpath = itd.next();
 81                 if(fpath.startsWith(dpath))
 82                     itf.remove();
 83             }
 84         }
 85         String dpath1,dpath2;
 86         Set<String> directories1 = new HashSet<>(directories);
 87         for(Iterator<String> itd1 = directories.iterator(); itd1.hasNext();) {
 88             dpath1 = itd1.next();
 89             for(Iterator<String> itd2 = directories1.iterator(); itd2.hasNext();) {
 90                 dpath2 = itd2.next();
 91                 if(dpath1.equals(dpath2))
 92                     continue;
 93                 else if(dpath2.startsWith(dpath1))
 94                     itd2.remove();
 95                 else if(dpath1.startsWith(dpath2))
 96                     itd1.remove();
 97             }
 98         }
 99         directories.addAll(directories1);
100         
101         fileArr.clear();
102         for(String file : files)
103             fileArr.add(new File(file));
104         for(String directory : directories)
105             fileArr.add(new File(directory));
106     }
btnBrowser_event_handler

  “重選”按鈕點選後清除已選項,邏輯就先不詳細介紹了。

  然後是“確定”按鈕,我們彈出檔案儲存框讓使用者選擇儲存位置,然後生成可執行的jar包:

 1 @Override
 2     public void actionPerformed(ActionEvent e) {
 3         if(e.getSource() == btnBrowser) {
 4         } else if(e.getSource() == btnCls) {
 5             if(userSelectedFiles.size() == 0) return;
 6             else if(JOptionPane.showConfirmDialog(this, "確定重選嗎?將清除所有已選項!") == JOptionPane.OK_OPTION) {
 7                 userSelectedFiles.clear();
 8                 finalFiles.clear();
 9                 filePaths.clear();
10                 cobMainClass.removeAllItems();
11             }
12         } else if(e.getSource() == btnConfirm) {
13             if(filePaths.size() == 0) {
14                 JOptionPane.showMessageDialog(this, "未選擇檔案", "錯誤", JOptionPane.ERROR_MESSAGE);
15                 return;
16             } else if(cobMainClass.getSelectedItem() == null) {
17                 JOptionPane.showMessageDialog(this, "未選擇啟動類", "錯誤", JOptionPane.ERROR_MESSAGE);
18                 return;
19             }
20             // 打包
21             int result = jfcSave.showSaveDialog(this);
22             if(result == JFileChooser.APPROVE_OPTION) {
23                 try {
24                     // 清單檔案
25                     Manifest man = new Manifest();
26                     // 版本和啟動類路徑必要
27                     man.getMainAttributes().putValue(Name.MANIFEST_VERSION.toString(), "1.0");
28                     man.getMainAttributes().putValue(Name.MAIN_CLASS.toString(), cobMainClass.getSelectedItem().toString());
29                     // Class-Path一定不要,除非能保證將引用類(即import的類)都聯合打包了
30                     JarOutputStream jos = new JarOutputStream(new FileOutputStream(jfcSave.getSelectedFile()), man);
31                     jos.setLevel(Deflater.BEST_COMPRESSION);
32                     BufferedInputStream bis = null;
33                     byte[] cache = new byte[1024];
34                     StringBuffer config = new StringBuffer();
35                     for(String name : filePaths.keySet()) {
36                         bis = new BufferedInputStream(new FileInputStream(filePaths.get(name)), 1024);
37                         config.append(name).append('=').append(bis.available()).append('\n');
38                         jos.putNextEntry(new JarEntry(name));
39                         int count;
40                         while((count = bis.read(cache, 0, 1024)) != -1)
41                             jos.write(cache, 0, count);
42                         jos.closeEntry();
43                         bis.close();
44                     }
45                     jos.flush();
46                     jos.close();
47                     JOptionPane.showMessageDialog(this, "匯出成功!", "成功", JOptionPane.INFORMATION_MESSAGE);
48                     System.exit(0);
49                 } catch(Exception ex) {
50                     JOptionPane.showMessageDialog(this, ex.getMessage(), "異常", JOptionPane.ERROR_MESSAGE);
51                     System.exit(1);
52                 }
53             }
54         }
55         
56     }
btnConfirm_event_handler

  當然,這裡還有一個小問題:選擇檔案(自己寫的檔名就算不加字尾也能儲存成功-_-)。

  先展示一下結果:

  

  在檔案系統中選擇:

  

  匯出到桌面:

  

  

  執行一下:

  

  我最後再將完整的原始碼貼出一份:

  1 package org.coderecord.commons.ejarmaker;
  2 
  3 import java.awt.Toolkit;
  4 import java.awt.event.ActionEvent;
  5 import java.awt.event.ActionListener;
  6 import java.io.BufferedInputStream;
  7 import java.io.File;
  8 import java.io.FileInputStream;
  9 import java.io.FileOutputStream;
 10 import java.util.ArrayList;
 11 import java.util.HashSet;
 12 import java.util.Hashtable;
 13 import java.util.Iterator;
 14 import java.util.List;
 15 import java.util.Map;
 16 import java.util.Set;
 17 import java.util.jar.JarEntry;
 18 import java.util.jar.JarOutputStream;
 19 import java.util.jar.Manifest;
 20 import java.util.jar.Attributes.Name;
 21 import java.util.zip.Deflater;
 22 
 23 import javax.swing.JButton;
 24 import javax.swing.JComboBox;
 25 import javax.swing.JFileChooser;
 26 import javax.swing.JFrame;
 27 import javax.swing.JLabel;
 28 import javax.swing.JOptionPane;
 29 import javax.swing.JScrollPane;
 30 import javax.swing.JTextArea;
 31 import javax.swing.filechooser.FileFilter;
 32 
 33 public class FrmMain extends JFrame implements ActionListener {
 34 
 35     private static final long serialVersionUID = 2016913328739206536L;
 36     // 選擇的檔案(使用者在檔案選擇器中選擇的)
 37     private List<File> userSelectedFiles = new ArrayList<>();
 38     // 我們經過分析得到的最終會被打包的檔案
 39     private List<File> finalFiles = new ArrayList<>();
 40     // 檔案打包路徑及物理檔案
 41     private Map<String, File> filePaths = new Hashtable<>();
 42     
 43     public FrmMain() {
 44         setSize(480, 320);
 45         setResizable(false);
 46         setLocationRelativeTo(null);
 47         setTitle("通用可執行Jar包生成工具");
 48         setDefaultCloseOperation(EXIT_ON_CLOSE);
 49         setLayout(null);
 50         // 在執行時獲取資原始檔的方式,一定是使用Class.getResource方式
 51         // 在jar包中這種方式也行得通
 52         // ‘/’代表根路徑
 53         setIconImage(Toolkit.getDefaultToolkit().getImage(FrmMain.class.getResource("/resources/icon.png")));
 54         initComponents();
 55     }
 56     
 57     // 初始化元件
 58     private void initComponents() {
 59         // 提示
 60         lblTip = new JLabel("選擇需要打包的檔案並設定啟動類");
 61         lblTip.setLocation(20, 10);
 62         lblTip.setSize(350, 20);
 63         add(lblTip);
 64         
 65         // 瀏覽按鈕
 66         btnBrowser = new JButton("瀏 覽");
 67         btnBrowser.setLocation(380, 10);
 68         btnBrowser.setSize(80, 24);
 69         btnBrowser.addActionListener(this);
 70         add(btnBrowser);
 71         
 72         // 展示已選擇檔案
 73         JScrollPane jspFiles = new JScrollPane();
 74         txtFiles = new JTextArea();
 75         txtFiles.setEditable(false);
 76         jspFiles.setSize(440, 160);
 77         jspFiles.setLocation(20, 40);
 78         txtFiles.setSize(440, 201600);
 79         txtFiles.setLocation(20, 40);
 80         txtFiles.setFocusable(false);
 81         jspFiles.setViewportView(txtFiles);
 82         add(jspFiles);
 83         
 84         // 選擇啟動類
 85         cobMainClass = new JComboBox<>();
 86         cobMainClass.setSize(440, 30);
 87         cobMainClass.setLocation(20, 210);
 88         add(cobMainClass);
 89         
 90         // 清除已選
 91         btnCls = new JButton("重 選");
 92         btnCls.setLocation(20, 250);
 93         btnCls.setSize(80, 24);
 94         btnCls.addActionListener(this);
 95         add(btnCls);
 96 
 97         // 確認按鈕
 98         btnConfirm = new JButton("確認");
 99         btnConfirm.setSize(80, 24);
100         btnConfirm.setLocation(380, 250);
101         btnConfirm.addActionListener(this);
102         add(btnConfirm);
103         
104         // 檔案選擇器
105         jfcSelect = new JFileChooser();
106         // 可以選擇檔案和資料夾
107         jfcSelect.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
108         // 可以多選
109         jfcSelect.setMultiSelectionEnabled(true);
110         
111         // 檔案儲存
112         jfcSave = new JFileChooser();
113         // 設定只接受以“.jar”結尾的檔案
114         jfcSave.setAcceptAllFileFilterUsed(false);
115         jfcSave.setFileFilter(new FileFilter() {
116             
117             @Override
118             public String getDescription() {
119                 return "可執行Jar";
120             }
121             
122             @Override
123             public boolean accept(File f) {
124                 return f.getName().endsWith(".jar");
125             }
126         });
127     }
128 
129     @Override
130     public void actionPerformed(ActionEvent e) {
131         if(e.getSource() == btnBrowser) {
132             // 瀏覽
133             int result = jfcSelect.showOpenDialog(this);
134 
135             // 選擇了檔案
136             if(result == JFileChooser.APPROVE_OPTION) {
137                 for(File file : jfcSelect.getSelectedFiles())
138                     userSelectedFiles.add(file);
139                 
140                 // 整理選擇的檔案,去除重複項
141                 removeDuplicateItems(userSelectedFiles);
142                 
143                 // 重新計算選中檔案
144                 finalFiles.clear();
145                 for(File file : userSelectedFiles)
146                     addFileToList(file, finalFiles);
147                 
148                 // 計算檔案展示打包路徑及展示路徑
149                 // 計算可啟動類路徑
150                 // 展示到文字框中
151                 cobMainClass.removeAllItems();
152                 txtFiles.setText("");
153                 File file,direc;
154                 String filePath,direcPath;
155                 Iterator<File> itd,itf;
156                 for(itd = userSelectedFiles.iterator(); itd.hasNext();) {
157                     direc = itd.next();
158                     direcPath = direc.getAbsolutePath();
159                     for(itf = finalFiles.iterator(); itf.hasNext();) {
160                         file = itf.next();
161                         filePath = file.getAbsolutePath();
162                         if(filePath.equalsIgnoreCase(direcPath)) {
163                             txtFiles.append(file.getName() + "\n");
164                             filePaths.put(file.getName(), file);
165                             if(file.getName().endsWith(".class"))
166                                 cobMainClass.addItem(file.getName().endsWith(".class")?file.getName().substring(0, file.getName().lastIndexOf('.')):file.getName());
167                             itf.remove();
168                         } else if(filePath.startsWith(direcPath)) {
169                             String nameTmp = filePath.substring(direcPath.lastIndexOf(File.separator) + 1).replace(File.separatorChar, '/'); 
170                             filePaths.put(nameTmp, file);
171                             txtFiles.append(nameTmp + "\n");
172                             if(nameTmp.endsWith(".class") && nameTmp.indexOf('$') == -1)
173                                 cobMainClass.addItem(nameTmp.substring(0, nameTmp.lastIndexOf('.')).replace('/', '.'));
174                             itf.remove();
175                         }
176                     }
177                 }
178             }
179         } else if(e.getSource() == btnCls) {
180             if(userSelectedFiles.size() == 0) return;
181             else if(JOptionPane.showConfirmDialog(this, "確定重選嗎?將清除所有已選項!") == JOptionPane.OK_OPTION) {
182                 userSelectedFiles.clear();
183                 finalFiles.clear();
184                 filePaths.clear();
185                 cobMainClass.removeAllItems();
186             }
187         } else if(e.getSource() == btnConfirm) {
188             if(filePaths.size() == 0) {
189                 JOptionPane.showMessageDialog(this, "未選擇檔案", "錯誤", JOptionPane.ERROR_MESSAGE);
190                 return;
191             } else if(cobMainClass.getSelectedItem() == null) {
192                 JOptionPane.showMessageDialog(this, "未選擇啟動類", "錯誤", JOptionPane.ERROR_MESSAGE);
193                 return;
194             }
195             // 打包
196             int result = jfcSave.showSaveDialog(this);
197             if(result == JFileChooser.APPROVE_OPTION) {
198                 try {
199                     // 清單檔案
200                     Manifest man = new Manifest();
201                     // 版本和啟動類路徑必要
202                     man.getMainAttributes().putValue(Name.MANIFEST_VERSION.toString(), "1.0");
203                     man.getMainAttributes().putValue(Name.MAIN_CLASS.toString(), cobMainClass.getSelectedItem().toString());
204                     // Class-Path一定不要,除非能保證將引用類(即import的類)都聯合打包了
205                     JarOutputStream jos = new JarOutputStream(new FileOutputStream(jfcSave.getSelectedFile()), man);
206                     jos.setLevel(Deflater.BEST_COMPRESSION);
207                     BufferedInputStream bis = null;
208                     byte[] cache = new byte[1024];
209                     StringBuffer config = new StringBuffer();
210                     for(String name : filePaths.keySet()) {
211                         bis = new BufferedInputStream(new FileInputStream(filePaths.get(name)), 1024);
212                         config.append(name).append('=').append(bis.available()).append('\n');
213                         jos.putNextEntry(new JarEntry(name));
214                         int count;
215                         while((count = bis.read(cache, 0, 1024)) != -1)
216                             jos.write(cache, 0, count);
217                         jos.closeEntry();
218                         bis.close();
219                     }
220                     jos.flush();
221                     jos.close();
222                     JOptionPane.showMessageDialog(this, "匯出成功!", "成功", JOptionPane.INFORMATION_MESSAGE);
223                     System.exit(0);
224                 } catch(Exception ex) {
225                     JOptionPane.showMessageDialog(this, ex.getMessage(), "異常", JOptionPane.ERROR_MESSAGE);
226                     System.exit(1);
227                 }
228             }
229         }
230         
231     }
232     
233     // 新增檔案(非資料夾)到集合
234     private void addFileToList(File file, List<File> fileArr) {
235         if(file.isDirectory())
236             for(File child : file.listFiles())
237                 addFileToList(child, fileArr);
238         else
239             fileArr.add(file);
240     }
241     
242     // 去除重複項
243     private void removeDuplicateItems(List<File> fileArr) {
244         // 去重複項
245         Set<String> directories = new HashSet<>();
246         Set<String> files = new HashSet<>();
247         for(File file : fileArr)
248             if(file.isDirectory())
249                 directories.add(file.getAbsolutePath());
250             else
251                 files.add(file.getAbsolutePath());
252         //去包含項(先去資料夾再去檔案應該更好)
253         String fpath,dpath;
254         for(Iterator<String> itf = files.iterator(); itf.hasNext();) {
255             fpath = itf.next();
256             for(Iterator<String> itd = directories.iterator(); itd.hasNext();) {
257                 dpath = itd.next();
258                 if(fpath.startsWith(dpath))
259                     itf.remove();
260             }
261         }
262         String dpath1,dpath2;
263         Set<String> directories1 = new HashSet<>(directories);
264         for(Iterator<String> itd1 = directories.iterator(); itd1.hasNext();) {
265             dpath1 = itd1.next();
266             for(Iterator<String> itd2 = directories1.iterator(); itd2.hasNext();) {
267                 dpath2 = itd2.next();
268                 if(dpath1.equals(dpath2))
269                     continue;
270                 else if(dpath2.startsWith(dpath1))
271                     itd2.remove();
272                 else if(dpath1.startsWith(dpath2))
273                     itd1.remove();
274             }
275         }
276         directories.addAll(directories1);
277         
278         fileArr.clear();
279         for(String file : files)
280             fileArr.add(new File(file));
281         for(String directory : directories)
282             fileArr.add(new File(directory));
283     }
284     
285     private JLabel lblTip;
286     private JButton btnBrowser;
287     private JFileChooser jfcSelect;
288     private JTextArea txtFiles;
289     private JComboBox<String> cobMainClass;
290     private JButton btnCls;
291     private JButton btnConfirm;
292     private JFileChooser jfcSave;
293 }
FrmMain

  這裡有我匯出的檔案(這個是eclipse匯出的,它在manifest中加入了classPath沒有錯誤,我有時候加入後有問題)。

 

 歡迎您移步我們的交流群,無聊的時候大家一起打發時間:Programmer Union

 或者通過QQ與我聯絡:點選這裡給我發訊息

 (最後編輯時間2014-03-02 16:12:50)

相關文章