import java.io.*; import java.util.Enumeration; import java.util.Vector; import java.awt.*; import java.awt.event.*; import javax.swing.*; import org.apache.tools.zip.*; //调用org.apache.tools.zip包,从压缩包中提取文件 public class ZipExtractDemo extends JFrame { private static final long serialVersionUID = 1L; JFileChooser fileChooser; // 文件选择器 JTextField jtfTarget; // 待解压文件路径 JButton jbSelected; // 选择文件按钮 JList files; // 信息显示列表框 JButton jbExtract; // 解压按钮 ZipFile zFile; public ZipExtractDemo() { super("从压缩包中提取文件"); // 调用父类构造函数 fileChooser = new JFileChooser(); // 实例化组件 jtfTarget = new JTextField(13); jbSelected = new JButton("选择"); jbExtract = new JButton("解压"); files = new JList(); JPanel panel = new JPanel(); // 实例化面板 panel.add(new JLabel("目标文件")); panel.add(jtfTarget); // 增加组件到面板上 panel.add(jbSelected); panel.add(jbExtract); JScrollPane jsp = new JScrollPane(files); // jsp.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); // // 设置边界 Container container = getContentPane(); // 得以容器 container.add(panel, BorderLayout.NORTH); // 增加组件到容器上 container.add(jsp, BorderLayout.CENTER); jbSelected.addActionListener(new ActionListener() { // 文件选择按钮事件处理 public void actionPerformed(ActionEvent event) { // 弹出文件选择器,并判断是否点击了打开按钮 if (fileChooser.showOpenDialog(ZipExtractDemo.this) == JFileChooser.APPROVE_OPTION) { String fileName = fileChooser.getSelectedFile() .getAbsolutePath(); // 得到选择文件的绝对路径 jtfTarget.setText(fileName); // 设置目标文件名 // showFiles(); // 显示压缩包内容 addFileToCompress("d:\\about.txt", fileName, "D:\\test.jar"); } } }); jbExtract.addActionListener(new ActionListener() { // 解压文件按钮事件处理 public void actionPerformed(ActionEvent event) { extractFile(files.getSelectedValue().toString()); // 解压指定文件 System.out.println("解压:" + files.getSelectedValue().toString()); } }); setSize(350, 250); // 设置窗口尺寸 setVisible(true); // 设置窗口可视 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 关闭窗口时退出程序 } /** * ********添加或覆盖一个文件到指定的压缩包中,参数一:资源文件路径,即需要添加的文件;***** * ********参数二:压缩包的路径;参数三:添加文件后生成新的压缩包的路径***** */ public void addFileToCompress(String res, String com, String out) { try { // 如果res文件与其它文件相同,此值将设为true并让res覆盖原有文件, // 如果最后此值为false,则添加res文件 boolean same = false; System.out.println("资源文件路径" + res + " , " + com); int index = res.lastIndexOf("\\") + 1;// 得到最后一个"\"符号的索引 String name = res.substring(index, res.length());// 截取文件名 // 文件输出流,生成out路径,也可以用此流写入数据并生成文件 FileOutputStream fos = new FileOutputStream(out); // 压缩输出流,通过此流把数据写放压缩包中 ZipOutputStream zOut = new ZipOutputStream(fos); // 压缩文件包,用于从压缩文件中读取条目 ZipFile zFile = new ZipFile(com); // 取得遍历条目对象 Enumeration enu = zFile.getEntries(); while (enu.hasMoreElements()) {// 判断是否有下一个遍历对象 // 取得遍历到的对象 ZipEntry zEntry = (ZipEntry) enu.nextElement(); // 得到对象名称,它包涵目录路径 String zEnName = zEntry.getName(); // 得到最后一个"/"符号的索引 int zEnIndex = zEnName.lastIndexOf("/") + 1; // 去除目录路径,取得纯文件名 String zEnSubName = zEnName.substring(zEnIndex, zEnName .length()); // 设置下一个要创建的Entry对象 zOut.putNextEntry(zEntry); // 判断名字是否一致,如果一致则写入指定的文件,否则写入原来的文件 if (zEnSubName.equals(name)) { // 文件输入流 FileInputStream fis = new FileInputStream(res); int len;// 长度 // 读取数据直到读完为止 while ((len = fis.read()) != -1) zOut.write(len); // 关闭输入流 fis.close(); same = true; } else { // 文件输入流 InputStream is = zFile.getInputStream(zEntry); int len;// 长度 // 读取数据直到读完为止 while ((len = is.read()) != -1) zOut.write(len); // 关闭输入流 is.close(); } } if (same == false) { // 设置下一个要创建的Entry对象 zOut.putNextEntry(new ZipEntry(name)); // 文件输入流 FileInputStream fis = new FileInputStream(res); int len;// 长度 // 读取数据直到读完为止 while ((len = fis.read()) != -1) zOut.write(len); // 关闭输入流 fis.close(); } // 关闭压缩输入流,此步骤是必须的,如果没有关闭则会让生成压缩包损坏 zOut.close(); } catch (Exception e) { e.printStackTrace(); } } /** 参数一:压缩输出流对象(此流用于写入数据并生成文件),参数二:需要压缩的File对象,参数三:根目录,即压缩包中的文件夹目录 */ public void zip(ZipOutputStream zOut, File file, String base) { try { System.out.println("正在压缩-->" + file.getName()); if (file.isDirectory()) { File[] listFiles = file.listFiles(); /* * 此处解决压缩未端数据不正确,这是判断当前是什么系统,普遍是Windows所以在这里就不注释不做此判断. if * (System.getProperty("os.name").startsWith("Windows")) { base = * base.length() == 0 ? "" : base + "\\"; out.putNextEntry(new * ZipEntry(base)); } else { base = base.length() == 0 ? "" : * base + "/"; out.putNextEntry(new ZipEntry(base)); } * 一般来说用"/"符号来分割出文件与文件夹是没有问题的 */ zOut.putNextEntry(new ZipEntry(base + "/")); base = base.length() == 0 ? "" : base + "/"; for (int i = 0; i < listFiles.length; i++) { zip(zOut, listFiles[i], base + listFiles[i].getName()); // System.out.println(new // String(fl[i].getName().getBytes("gb2312"))); } } else { if (base == "") { base = file.getName(); } zOut.putNextEntry(new ZipEntry(base)); FileInputStream in = new FileInputStream(file); int len; while ((len = in.read()) != -1) zOut.write(len); in.close(); } } catch (Exception e) { e.printStackTrace(); } } public void showFiles() { try { zFile = new ZipFile(jtfTarget.getText()); // 得到压缩文件实例 ZipEntry entry; Vector vec = new Vector(); // 文件枚举 Enumeration enu = zFile.getEntries(); // 得到压缩条目的枚举对象 while (enu.hasMoreElements()) { // 依次枚举条目 entry = (ZipEntry) enu.nextElement(); // 得到压缩条目 vec.add(entry.getName()); // 增加文件到Vector内 } files.setListData(vec); // 设置文件列表框数据 files.getSelectedValues(); } catch (Exception ex) { ex.printStackTrace(); // 输出错误信息 } } public void extractFile(String name) { // 解压文件 try { ZipEntry entry = zFile.getEntry(name); entry.getComment(); entry.getCompressedSize(); entry.getCrc(); entry.isDirectory(); entry.getSize(); entry.getMethod(); InputStream in = zFile.getInputStream(entry); // 得到文件输入流 File file = new File("D://index.txt"); // 实例化文件对象 FileOutputStream out = new FileOutputStream(file); // 得到文件输出流 byte[] buffer = new byte[1024]; // 缓冲区大小 int length = 0; while ((length = in.read(buffer)) != -1) { // 循环读取数据 out.write(buffer, 0, length); // 写数据到输出流 } JOptionPane.showMessageDialog(ZipExtractDemo.this, "解压成功,解压到:" + file.getAbsolutePath()); in.close(); // 关闭输入流 out.close(); // 关闭输出流 } catch (Exception ex) { } } public static void main(String[] args) { new ZipExtractDemo(); } }