隨筆 - 117  文章 - 72  trackbacks - 0

          聲明:原創(chuàng)作品(標(biāo)有[原]字樣)轉(zhuǎn)載時(shí)請(qǐng)注明出處,謝謝。

          常用鏈接

          常用設(shè)置
          常用軟件
          常用命令
           

          訂閱

          訂閱

          留言簿(7)

          隨筆分類(lèi)(130)

          隨筆檔案(123)

          搜索

          •  

          積分與排名

          • 積分 - 155774
          • 排名 - 390

          最新評(píng)論

          [關(guān)鍵詞]:ant,zip,unzip,Apache,壓縮,解壓,中文亂碼,ZipEntry
               先前寫(xiě)了一篇blog《使用org.apache.tools.zip實(shí)現(xiàn)zip壓縮和解壓》,現(xiàn)對(duì)它進(jìn)行了改進(jìn):找出了幾個(gè)Bug,修改了部分代碼,增加了注釋?zhuān)砑恿藞D形界面,打了個(gè)可執(zhí)行包,雙就可以運(yùn)行了。源代碼如下,希望大家多提意見(jiàn)。

          MyZip.java:
          package myzip;
          import java.io.*;
          import javax.swing.*;
          import java.awt.*;
          import java.awt.event.*;
          import myzip.AntZip;

          /**
           *界面類(lèi),調(diào)用AntZip類(lèi)實(shí)現(xiàn)壓縮解壓功能。
           *@version 2009-3-18
           *@author Winty (wintys@gmail.com)
           */
          public class MyZip{
              public static void main(String[] args){
                  new MyZip(new AntZip());
              }

              public MyZip(AntZip zip){
                  this.zip = zip;
                  this.latestDir = new File(".");
                  buildUI();       
              }

              public void buildUI(){
                  jframe = new JFrame();
                  jframe.setTitle("MyZip");
                  jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                  jframe.setResizable(false);
                  jframe.setSize(230 , 150);
                  Dimension screen= Toolkit.getDefaultToolkit().getScreenSize();
                  jframe.setLocation((screen.width-jframe.getWidth())/2,
                                               (screen.height-jframe.getWidth())/2);

                  jframe.setLayout(null);
                  Container contentPane = jframe.getContentPane();

                  JButton zipBtn;
                  JButton unzipBtn;
                  zipBtn = new JButton("壓縮");
                  unzipBtn = new JButton("解壓");
                  zipBtn.setSize(60 , 40);
                  unzipBtn.setSize(60 , 40);
                  zipBtn.setLocation(40,40);
                  unzipBtn.setLocation(120 , 40);
                  contentPane.add(zipBtn);
                  contentPane.add(unzipBtn);

                  zipBtn.addActionListener(new ActionHandler());
                  unzipBtn.addActionListener(new ActionHandler());

                  jframe.setVisible(true);
              }

              private JFrame jframe;
              private AntZip zip;
              private File latestDir;/*記錄最近使用的文件夾路徑*/

              /*內(nèi)部類(lèi)監(jiān)聽(tīng)器*/
              class ActionHandler implements ActionListener{
                  public void actionPerformed(ActionEvent event){
                      JFileChooser chooser = new JFileChooser();
                      chooser.setCurrentDirectory(latestDir);

                      String cmd = event.getActionCommand();
                      if(cmd.equals("壓縮")){
                          chooser.setFileSelectionMode(
                              JFileChooser.FILES_AND_DIRECTORIES);
                          chooser.setMultiSelectionEnabled(true);

                          int returnVal = chooser.showOpenDialog(jframe);
                          if(returnVal == JFileChooser.APPROVE_OPTION) {
                              File[] files = chooser.getSelectedFiles();
                              if(files!=null){
                                  zip.doZip(files , files[0].getName());
                                  latestDir = files[0].getParentFile();
                              }
                          }
                      }
                      else if(cmd.equals("解壓")){
                          chooser.setMultiSelectionEnabled(false) ;

                          int returnVal = chooser.showOpenDialog(jframe);
                          if(returnVal == JFileChooser.APPROVE_OPTION) {
                              File file = chooser.getSelectedFile();
                              if(file!=null){
                                  zip.unZip(file);
                                  latestDir = file.getParentFile();
                              }
                          }
                      }

                  }
              }
          }

          AntZip.java:
          package myzip;
          import java.io.*;
          import org.apache.tools.zip.*;
          import java.util.Enumeration;
          /**
          *功能:zip壓縮、解壓(支持中文文件名)
          *說(shuō)明:使用Apache Ant提供的zip工具org.apache.tools.zip實(shí)現(xiàn)zip壓縮和解壓功能.
          *   解決了由于java.util.zip包不支持漢字的問(wèn)題。
          *   使用java.util.zip包時(shí),當(dāng)zip文件中有名字為中文的文件時(shí),
          *   就會(huì)出現(xiàn)異常:
          *        "Exception  in thread "main " java.lang.IllegalArgumentException
          *      at   java.util.zip.ZipInputStream.getUTF8String(ZipInputStream.java:285)
          *
          *注意:
          *   1、使用時(shí)把a(bǔ)nt.jar放到classpath中,程序中使用import org.apache.tools.zip.*;
          *   2、Apache Ant 下載地址:http://ant.apache.org/
          *   3、Ant ZIP Online API:
          *www.jajakarta.org/ant/ant-1.6.1/docs/mix/manual/api/org/apache/tools/zip/
          *   4、本程序使用Ant 1.7.1 中的ant.jar。
          *   5、如果只需要Ant的zip壓縮功能,不需要Ant的其它功能,
          *     那么可以減小ant.jar的大小。方法是用WinRAR打開(kāi)ant.jar,
          *     把沒(méi)有用到的包和class文件都刪除。這樣ant.jar體積就減小了。
          *   6、ZipEntry的isDirectory()方法中,目錄以"/"結(jié)尾。
          *
          *僅供編程學(xué)習(xí)參考.
          *
          *Copyright (c) Winty
          *http://www.aygfsteel.com/wintys
          *
          *@author Winty (wintys@gmail.com)
          *@version   2008-8-3
          *------------------------------------------------
          *可將主函數(shù)注釋去掉以單獨(dú)測(cè)試AntZip類(lèi)。
          *Compile:
          *   javac -cp Ant.jar AntZip.java
          *
          *Usage:(將ant.jar直接放在當(dāng)前目錄)
          *   壓縮:java -cp Ant.jar;.  AntZip -zip [directoryName | fileName]...
          *   解壓:java -cp Ant.jar;.  AntZip -unzip "fileName.zip"
          *
          *------------------------------------------------
          *2009-3-17:
          *修正一處Bug,當(dāng)解壓的zip文件中根目錄下直接有文件時(shí)會(huì)出錯(cuò)。
          *將unZip()中的if(!parent.exists())改正為:if(parent!=null && !parent.exists())
          *
          *2009-3-18:
          *多處其它修改
          *------------------------------------------------
          */

          public class AntZip{
              private ZipFile         zipFile;
              private ZipOutputStream zipOut;     //壓縮Zip
              private ZipEntry        zipEntry;
              private static int      bufSize;    //size of bytes
              private byte[]          buf;
              private int             readedBytes;
              //用于壓縮中。要去除的絕對(duì)父路路徑,目的是將絕對(duì)路徑變成相對(duì)路徑。
              private String deleteAbsoluteParent;
             
              /**
               *構(gòu)造方法。默認(rèn)緩沖區(qū)大小為512字節(jié)。
               */
              public AntZip(){
                  this(512);
              }

              /**
               *構(gòu)造方法。
               *@param bufSize 指定壓縮或解壓時(shí)的緩沖區(qū)大小
               */
              public AntZip(int bufSize){
                  this.bufSize = bufSize;
                  this.buf = new byte[this.bufSize];
                  deleteAbsoluteParent = null;
              }
             
              /**
               *壓縮文件夾內(nèi)的所有文件和目錄。
               *@param zipDirectory 需要壓縮的文件夾名
               */
              public void doZip(String zipDirectory){
                  File zipDir = new File(zipDirectory);
                  doZip(new File[]{zipDir} , zipDir.getName());
              }

              /**
               *壓縮多個(gè)文件或目錄。可以指定多個(gè)單獨(dú)的文件或目錄。而
               *<code>doZip(String zipDirectory)</code>則直接壓縮整個(gè)文件夾。
               *@param files 要壓縮的文件或目錄組成的<code>File</code>數(shù)組。
               *@param zipFileName 壓縮后的zip文件名,如果后綴不是".zip",
               *  自動(dòng)添加后綴".zip"。
               */
              public void doZip(File[] files , String zipFileName){
                  //未指定壓縮文件名,默認(rèn)為"ZipFile"
                  if(zipFileName==null || zipFileName.equals(""))
                      zipFileName = "ZipFile";

                  //添加".zip"后綴
                  if(!zipFileName.endsWith(".zip"))
                      zipFileName += ".zip";

                  try{
                      this.zipOut = new ZipOutputStream(
                          new BufferedOutputStream(new FileOutputStream(zipFileName)));
                      compressFiles(files , this.zipOut , true );
                      this.zipOut.close();
                  }catch(IOException ioe){
                      ioe.printStackTrace();
                  }
              }

              /**
               *壓縮文件和目錄。由doZip()調(diào)用
               *@param files 要壓縮的文件
               *@param zipOut zip輸出流
               *@param isAbsolute 是否是要去除的絕對(duì)路徑的根路徑。因?yàn)閏ompressFiles()
               *會(huì)遞歸地被調(diào)用,所以只用deleteAbsoluteParent不行。必須用isAbsolute來(lái)指明
               *compressFiles()是第一次調(diào)用,而不是后續(xù)的遞歸調(diào)用。即如果要壓縮的路徑是
               *E:\temp,那么第一次調(diào)用時(shí),isAbsolute=true,則deleteAbsoluteParent會(huì)記錄
               *要?jiǎng)h除的路徑就是E:\ ,當(dāng)壓縮子目錄E:\temp\folder時(shí),isAbsolute=false,
               *再遞歸調(diào)用compressFiles()時(shí),deleteAbsoluteParent仍然是E:\ 。從而保證了
               *將E:\temp及其子目錄均正確地轉(zhuǎn)化為相對(duì)目錄。這樣壓縮才不會(huì)出錯(cuò)。不然絕對(duì)
               *路徑E:\也會(huì)被寫(xiě)入到壓縮文件中去。
               */
              private void compressFiles(File[] files ,
                                                      ZipOutputStream zipOut ,
                                                      boolean isAbsolute) throws IOException{

                  for(File file : files){
                      if(file==null)continue; //空的文件對(duì)象

                      //刪除絕對(duì)父路徑
                      if(file.isAbsolute()){
                          if(isAbsolute){
                              deleteAbsoluteParent = file.getParentFile().getAbsolutePath();
                              deleteAbsoluteParent = appendSeparator(deleteAbsoluteParent);
                          }
                      }
                      else
                          deleteAbsoluteParent = "";

                      if(file.isDirectory()){//是目錄
                          compressFolder(file , zipOut);
                      }
                      else{//是文件
                          compressFile(file , zipOut);
                      }
                  }
              }

              /**
               *壓縮文件或空目錄。由compressFiles()調(diào)用。
               *@param file 需要壓縮的文件
               *@param zipOut zip輸出流
               */
              public void compressFile(File file , ZipOutputStream zipOut)
                  throws IOException{

                  String fileName = file.toString();

                  /*去除絕對(duì)父路徑。*/
                  if(file.isAbsolute())
                      fileName = fileName.substring(deleteAbsoluteParent.length());
                  if(fileName == null || fileName=="")
                      return;


                  /*因?yàn)槭强漳夸洠砸诮Y(jié)尾加一個(gè)"/"。
                    不然就會(huì)被當(dāng)作是空文件。
                    ZipEntry的isDirectory()方法中,目錄以"/"結(jié)尾.
                    org.apache.tools.zip.ZipEntry :
                      public boolean isDirectory() {
                          return getName().endsWith("/");
                      }
                    */
                  if(file.isDirectory())
                      fileName = fileName + "/";//此處不能用"\\"

                  zipOut.putNextEntry(new ZipEntry(fileName));

                  //如果是文件則需讀;如果是空目錄則無(wú)需讀,直接轉(zhuǎn)到zipOut.closeEntry()。
                  if(file.isFile()){
                      FileInputStream fileIn = new FileInputStream(file);
                      while((this.readedBytes = fileIn.read(this.buf))>0){
                          zipOut.write(this.buf , 0 , this.readedBytes);
                      }
                      fileIn.close();
                  }

                  zipOut.closeEntry();
              }

              /**
               *遞歸完成目錄文件讀取。由compressFiles()調(diào)用。
               *@param dir 需要處理的文件對(duì)象
               *@param zipOut zip輸出流
               */
              private void compressFolder(File dir , ZipOutputStream zipOut)
                  throws IOException{
                 
                  File[] files = dir.listFiles();
             
                  if(files.length == 0)//如果目錄為空,則單獨(dú)壓縮空目錄。
                      compressFile(dir , zipOut);
                  else//如果目錄不為空,則分別處理目錄和文件.
                      compressFiles(files , zipOut , false);
              }
             
              /**
               *解壓指定zip文件。
               *@param unZipFileName 需要解壓的zip文件名
               */
              public void unZip(String unZipFileName){
                  FileOutputStream fileOut;
                  File file;
                  InputStream inputStream;

                  try{
                      this.zipFile = new ZipFile(unZipFileName);

                      for(Enumeration entries = this.zipFile.getEntries();
                          entries.hasMoreElements(); ){

                          ZipEntry entry = (ZipEntry)entries.nextElement();
                          file = new File(entry.getName());

                          if(entry.isDirectory()){//是目錄,則創(chuàng)建之
                              file.mkdirs();
                          }
                          else{//是文件
                              //如果指定文件的父目錄不存在,則創(chuàng)建之.
                              File parent = file.getParentFile();
                              if(parent!=null && !parent.exists()){
                                  parent.mkdirs();
                              }

                              inputStream = zipFile.getInputStream(entry);

                              fileOut = new FileOutputStream(file);
                              while(( this.readedBytes = inputStream.read(this.buf) ) > 0){
                                  fileOut.write(this.buf , 0 , this.readedBytes );
                              }
                              fileOut.close();

                              inputStream.close();
                          }  
                      }
                      this.zipFile.close();
                  }catch(IOException ioe){
                      ioe.printStackTrace();
                  }
              }

             
              /**
               *給文件路徑或目錄結(jié)尾添加File.separator
               *@param fileName 需要添加路徑分割符的路徑
               *@return 如果路徑已經(jīng)有分割符,則原樣返回,否則添加分割符后返回。
               */
              private String appendSeparator(String path){
                  if(!path.endsWith(File.separator))
                                  path += File.separator;
                  return path;
              }

              /**
               *解壓指定zip文件。
               *@param unZipFile 需要解壓的zip文件對(duì)象
               */
              public void unZip(File unZipFile){
                  unZip(unZipFile.toString());
              }

              /**
               *設(shè)置壓縮或解壓時(shí)緩沖區(qū)大小。
               *@param bufSize 緩沖區(qū)大小
               */
              public void setBufSize(int bufSize){
                  this.bufSize = bufSize;
              }

              //主函數(shù),用于測(cè)試AntZip類(lèi)
              /*
              public static void main(String[] args)throws Exception{
                  if(args.length>=2){
                      AntZip zip = new AntZip();

                      if(args[0].equals("-zip")){
                          //將后續(xù)參數(shù)全部轉(zhuǎn)化為File對(duì)象
                          File[] files = new File[ args.length - 1];
                          for(int i = 0;i < args.length - 1; i++){
                              files[i] = new File(args[i + 1]);
                          }

                          //將第一個(gè)文件名作為zip文件名
                          zip.doZip(files , files[0].getName());

                          return ;
                      }
                      else if(args[0].equals("-unzip")){
                          zip.unZip(args[1]);
                          return ;
                      }
                  }
                 
                  System.out.println("Usage:");
                  System.out.println("壓縮:java AntZip -zip [directoryName | fileName]... ");
                  System.out.println("解壓:java AntZip -unzip fileName.zip");
              }
              */
          }

          附件內(nèi)容:
          /MyZip.jar : 打包后的可執(zhí)行文件,可單獨(dú)運(yùn)行,內(nèi)含org.apache.tools.zip包。運(yùn)行環(huán)境JRE1.6+
          /使用Ant實(shí)現(xiàn)zip壓縮解壓功能/ant.jar : 精簡(jiǎn)后的ant包,只包含org.apache.tools.zip
          /使用Ant實(shí)現(xiàn)zip壓縮解壓功能/AntZip.java
          /使用Ant實(shí)現(xiàn)zip壓縮解壓功能/MyZip.java

          [附件]:使用Ant實(shí)現(xiàn)zip壓縮解壓功能.zip
          posted on 2009-03-19 13:17 天堂露珠 閱讀(4767) 評(píng)論(11)  編輯  收藏 所屬分類(lèi): Java

          FeedBack:
          # re: [原]使用Ant實(shí)現(xiàn)zip壓縮解壓功能 2009-06-11 16:23 豬影橫飛
          你好,學(xué)習(xí)了你的ANT實(shí)現(xiàn)ZIP壓縮技術(shù),受益匪淺,想問(wèn)下,如果我想做成壓縮雙機(jī)文件通信(即采用服務(wù)端/客戶(hù)端形式),點(diǎn)擊發(fā)送端按鈕->選擇文件->壓縮成*.zip文件->發(fā)送給客戶(hù)端,點(diǎn)擊接收端按鈕->選擇保存路徑->接收*.zip文件->解壓*.zip文件,請(qǐng)問(wèn)如何實(shí)現(xiàn)和調(diào)用?
          hszcy521@163.com  回復(fù)  更多評(píng)論
            
          # re: [原]使用Ant實(shí)現(xiàn)zip壓縮解壓功能 2009-06-11 20:17 天堂露珠
          那就需要用到TCP或UDP通信了,參見(jiàn)我的CSDN文章:《Java UDP網(wǎng)絡(luò)編程 - 最簡(jiǎn)單示例》:http://blog.csdn.net/wintys/archive/2008/12/15/3525643.aspx ,以及《Java TCP網(wǎng)絡(luò)編程 - 最簡(jiǎn)單示例》:http://blog.csdn.net/wintys/archive/2008/12/15/3525619.aspx 。  回復(fù)  更多評(píng)論
            
          # re: [原]使用Ant實(shí)現(xiàn)zip壓縮解壓功能 2009-06-11 21:56 豬影橫飛
          恩,這個(gè)我會(huì)寫(xiě)已經(jīng)寫(xiě)好了SERVER.JAVA和CLIENT.JAVA了,但里邊都帶有main函數(shù),在JDK編程的環(huán)境下能直接運(yùn)行,我想問(wèn)的就是如何再GUI.JAVA里的事件處理中按我的流程調(diào)用?服務(wù)端先壓縮再傳送,客戶(hù)端先接收再解壓  回復(fù)  更多評(píng)論
            
          # re: [原]使用Ant實(shí)現(xiàn)zip壓縮解壓功能 2009-06-11 23:16 天堂露珠
          @豬影橫飛
          兩個(gè)客戶(hù)端都一直在監(jiān)聽(tīng)著指定的端口,用線程實(shí)現(xiàn)監(jiān)聽(tīng)。
          以下僅為示意性代碼:

          1、發(fā)送
          比如就用我寫(xiě)的MyZip.java的界面,把"壓縮"改成"發(fā)送",
          if(cmd.equals("壓縮")){
          ......
          if(files!=null){
          //先壓縮所選文件夾內(nèi)的文件,結(jié)果會(huì)生成一個(gè)zip文件,假設(shè)為"file.zip"
          zip.doZip(files , files[0].getName());
          latestDir = files[0].getParentFile();

          //udp為UDP通信類(lèi)。
          //獲取"file.zip"的字節(jié)數(shù)組,啟動(dòng)一個(gè)線程,
          //把它當(dāng)作一個(gè)或多個(gè)數(shù)據(jù)包發(fā)送出去,
          //而此時(shí),另一個(gè)客戶(hù)端正在監(jiān)聽(tīng)著,它收到數(shù)據(jù)后,進(jìn)行相反的操作。
          udp.send(filePacket);
          }
          ......
          }


          2、接收
          也就是說(shuō),沒(méi)有數(shù)據(jù)發(fā)送的時(shí)候,兩個(gè)客戶(hù)端都有一個(gè)后臺(tái)線程運(yùn)行著:
          class Client implements Runnable{
          public void run(){
          while(true){
          //接收,沒(méi)有收到時(shí),將一直等待
          datagramSocket.receive(recvPacket);
          //解壓
          Unzip();
          }
          }
          }  回復(fù)  更多評(píng)論
            
          # re: [原]使用Ant實(shí)現(xiàn)zip壓縮解壓功能 2009-06-12 22:36 豬影橫飛
          @天堂露珠
          謝謝你的指點(diǎn),非常感謝!~  回復(fù)  更多評(píng)論
            
          # re: [原]使用Ant實(shí)現(xiàn)zip壓縮解壓功能 2009-06-13 21:07 王琦均
          如果是要求以流的形式傳入zip文件,那怎么解決呢
          我看了ant里面好像沒(méi)有提供這樣的方法。
          里面 沒(méi)有zipInputStream 只有zipOutputStream

          我這里提的方法就是:
          //這里的流就是出入的zip文件流
          public int getText(InputStream is){

          }  回復(fù)  更多評(píng)論
            
          # re: [原]使用Ant實(shí)現(xiàn)zip壓縮解壓功能 2009-06-13 22:34 天堂露珠
          @王琦均
          只有自己獨(dú)立解決問(wèn)題,才可能真正成長(zhǎng),不能每一步都問(wèn)吧。
          其實(shí)我的程序中已經(jīng)用到了,org.apache.tools.zip.ZipFile.getInputStream(ZipEntry ze)就是輸入流。  回復(fù)  更多評(píng)論
            
          # re: [原]使用Ant實(shí)現(xiàn)zip壓縮解壓功能 2009-06-14 01:20 王琦均
          @天堂露珠
          外部只調(diào)我這個(gè)程序的這個(gè)方法哦
          也就是外部程序只給我傳個(gè)流進(jìn)來(lái)。  回復(fù)  更多評(píng)論
            
          # re: [原]使用Ant實(shí)現(xiàn)zip壓縮解壓功能 2009-06-14 01:23 王琦均
          @天堂露珠
          外部是不會(huì)用org.apache.tools.zip.ZipFile.getInputStream(ZipEntry ze)
          來(lái)給你轉(zhuǎn)化的。
          直接就是個(gè)文件流傳進(jìn)來(lái)的!  回復(fù)  更多評(píng)論
            
          # re: [原]使用Ant實(shí)現(xiàn)zip壓縮解壓功能 2009-06-29 15:41 shappy
          @王琦均 可能我的答案是你想要的,你是希望直接輸出zip流,而不是zip文件嗎
          //創(chuàng)建zip流
          ByteArrayOutputStream out = new ByteArrayOutputStream();
          ZipOutputStream zout = new ZipOutputStream(out);
          //省略
          ByteArrayInputStream zin= new ByteArrayInputStream(out.toByteArray());
          byte[] aryRead = new byte[zin.available()];
          //有inputstream,也有byte[]

            回復(fù)  更多評(píng)論
            
          # re: [原]使用Ant實(shí)現(xiàn)zip壓縮解壓功能 2009-06-29 15:51 shappy
          //創(chuàng)建zip流
          ByteArrayOutputStream out = new ByteArrayOutputStream();
          ZipOutputStream zout = new ZipOutputStream(out);
          //省略壓縮代碼
          zout.close(); //很奇怪,這里如果不關(guān)閉的話(huà),檢測(cè)到輸出的流稍小一點(diǎn),而且數(shù)據(jù)也有一些差異,誰(shuí)能解釋一下
          ByteArrayInputStream zin= new ByteArrayInputStream(out.toByteArray());
          byte[] aryRead = new byte[zin.available()];
          //有inputstream,也有byte[]   回復(fù)  更多評(píng)論
            
          主站蜘蛛池模板: 长丰县| 兴山县| 水城县| 自贡市| 汝城县| 新和县| 梅河口市| 武穴市| 焦作市| 新化县| 保山市| 黑龙江省| 寿阳县| 达孜县| 宜川县| 南雄市| 馆陶县| 泸水县| 灯塔市| 黎平县| 宜君县| 湖南省| 上栗县| 洛川县| 永春县| 中西区| 林芝县| 黎城县| 洛阳市| 楚雄市| 威宁| 沁阳市| 新建县| 乐山市| 称多县| 图片| 台北县| 安康市| 桂平市| 松溪县| 牡丹江市|