博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
使用原生Java代码生成可执行Jar包
阅读量:5103 次
发布时间:2019-06-13

本文共 24890 字,大约阅读时间需要 82 分钟。

  最近想做一个功能,就是把我们编译后的字节码及其资源文件打包成一个可执行的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             @Override19             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
userSelectedFiles = new ArrayList<>(); 24 // 我们经过分析得到的最终会被打包的文件 25 private List
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 @Override102 public String getDescription() {103 return "可执行Jar";104 }105 106 @Override107 public boolean accept(File f) {108 return f.getName().endsWith(".jar");109 }110 });111 }112 113 @Override114 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
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
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
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
fileArr) { 67 // 去重复项 68 Set
directories = new HashSet<>(); 69 Set
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
itf = files.iterator(); itf.hasNext();) { 78 fpath = itf.next(); 79 for(Iterator
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
directories1 = new HashSet<>(directories); 87 for(Iterator
itd1 = directories.iterator(); itd1.hasNext();) { 88 dpath1 = itd1.next(); 89 for(Iterator
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
userSelectedFiles = new ArrayList<>(); 38 // 我们经过分析得到的最终会被打包的文件 39 private List
finalFiles = new ArrayList<>(); 40 // 文件打包路径及物理文件 41 private Map
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 @Override118 public String getDescription() {119 return "可执行Jar";120 }121 122 @Override123 public boolean accept(File f) {124 return f.getName().endsWith(".jar");125 }126 });127 }128 129 @Override130 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
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
fileArr) {235 if(file.isDirectory())236 for(File child : file.listFiles())237 addFileToList(child, fileArr);238 else239 fileArr.add(file);240 }241 242 // 去除重复项243 private void removeDuplicateItems(List
fileArr) {244 // 去重复项245 Set
directories = new HashSet<>();246 Set
files = new HashSet<>();247 for(File file : fileArr)248 if(file.isDirectory())249 directories.add(file.getAbsolutePath());250 else251 files.add(file.getAbsolutePath());252 //去包含项(先去文件夹再去文件应该更好)253 String fpath,dpath;254 for(Iterator
itf = files.iterator(); itf.hasNext();) {255 fpath = itf.next();256 for(Iterator
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
directories1 = new HashSet<>(directories);264 for(Iterator
itd1 = directories.iterator(); itd1.hasNext();) {265 dpath1 = itd1.next();266 for(Iterator
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
cobMainClass;290 private JButton btnCls;291 private JButton btnConfirm;292 private JFileChooser jfcSave;293 }
FrmMain

  有我导出的文件(这个是eclipse导出的,它在manifest中加入了classPath没有错误,我有时候加入后有问题)。

 

 欢迎您移步我们的交流群,无聊的时候大家一起打发时间:

 或者通过QQ与我联系:

 (最后编辑时间2014-03-02 16:12:50)

转载于:https://www.cnblogs.com/Johness/p/3576920.html

你可能感兴趣的文章
mysql 自动加上编号
查看>>
Message no. C6015--No valuation variant found for valuation area xxxx
查看>>
Program Variant Scheduling job
查看>>
.net之路
查看>>
题目2-括号配对问题
查看>>
python 面向对象oop
查看>>
linux 安装 Django
查看>>
Heap:Sunscreen(POJ 3614)
查看>>
Storm-源码分析-Streaming Grouping (backtype.storm.daemon.executor)
查看>>
Hadoop TDG 2 – I/O
查看>>
C#中 As 和强制转换的总结
查看>>
POJ2227(优先队列)
查看>>
PCB 铺铜
查看>>
Calendar(显示日期)
查看>>
一周最新示例代码回顾 (4/23–4/29)
查看>>
转载:字符串的驻留(String Interning)
查看>>
C语言指针总结
查看>>
monoGSM信号强度示例
查看>>
软件工程--功能规格说明书
查看>>
POJ 1065 学习写法
查看>>