亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > Java > 正文

java多線程實現下載圖片并壓縮

2024-07-14 08:40:50
字體:
來源:轉載
供稿:網友

最近在做一個需求:從其他系統的ftp目錄下載存儲圖片url的文件,然后讀取文件中的url地址,根據地址下載圖片后按天壓縮成一個包,平均一個地址文件中包含4000個地址左右,也就是說一個文件掃描后需要下載4000個左右的圖片,然后壓縮,下面把我的實現方式和優化過程記錄下來,如果大家有什么更好的方式可以分享。

使用框架:SpringMVC

定時任務實現:繼承org.springframework.scheduling.quartz.QuartzJobBean;

ftp環境搭建就不說了,在其他博客記錄過,使用虛擬機中的CentOS搭建的FTP服務,創建FTP賬號及對應目錄,事先上傳需要下載的圖片地址文件。文件內容格式“圖片ID||圖片地址”。

方法一、最簡單的實現方法就是先下載存儲圖片url地址的文件,然后讀取文件遍歷圖片地址,調下載圖片的方法將圖片存儲到本地,最后壓縮下載的圖片,完成后刪除下載的圖片,只保留壓縮包。

public class PictureTransferJob extends QuartzJobBean {  protected void executeInternal(JobExecutionContext arg0) throws JobExecutionException  {  //實際的FTP配置是讀取配置文件獲取的  //FTP地址  String hostName ="192.168.1.112";  //FTP端口  int port = 2001;  /FTP賬號  String userName = "test1";  //ftp密碼  String password = "test1";  //ftp文件存儲目錄  String ftpDowload = "/";  //文件本地存儲路徑  String path = this.getClass().getResource("/").getPath();  //圖片地址文件存儲目錄  String addrPath=path.substring(1, path.indexOf("WEB-INF/classes"))+"picAddr";  //實際下載的圖片存儲目錄  String picPath=path.substring(1, path.indexOf("WEB-INF/classes"))+"pic";  addrPath = addrPath.replace("%20"," ");  picPath = picPath.replace("%20"," ");  try  {  //創建存儲圖片地址的文件  creatFile(addrPath);  //創建存儲實際圖片的文件  creatFile(picPath);  String oldAddrPath = addrPath;  String oldPicPath = picPath;  //創建FTP連接  FtpUtil2 ftpUtil2 = new FtpUtil2(hostName, port,userName, password, ftpDowload, true);  //遍歷FTP目錄下的文件  String[] files = ftpUtil2.ListAllFiles();  //本地數據庫會有一個表記錄下載過的文件,這里會查詢數據庫和ftp列出的文件名比較,如果已經下載過的文件就不會下載,避免重復下載。  //下面省略比較的過程,循環files數組,在本地創建文件  for(int i=0;i<files.length;i++){  creatFile(addrPath+File.separator+fileName);  //ftpDowload是ftp服務器存儲文件的地址,addrPath是本地存儲文件的地址  //這里一個返回狀態判斷文件是否下載成功  boolean downloadInvestorFlag = ftpUtil2.downloadFile(ftpDowload, addrPath);  //文件下載成功后調讀取文件的方法,將需要下載的圖片地址存入容器  boolean entityState = setPictureDetail(addrPath,picPath,fileNameDate);  }  }   catch (Exception e)  {   e.printStackTrace();   //調記錄錯誤日志的業務類用于發送下載文件出錯的短信  } }   //這里開始讀圖片地址 private boolean setPictureDetail(String addrPath,String picPath,String synDate) {  System.out.println("----------進入setPictureDetail方法-----------");  BufferedReader br = null;  try  {   br=new BufferedReader(new InputStreamReader(new FileInputStream(addrPath),"UTF-8"));   String row;   int count=0;  //map中存儲每行讀取到的圖片名稱和URL地址   Map<String, String> addrMap=new HashMap<String, String>();   while ((row=br.readLine())!=null)   {   try   {    count++;    if (count==1)    {    continue;    }    String[] column = row.split("//|//|", -1);    addrMap.put(column[0].trim(), column[1].trim());   }   catch (Exception e)   {    e.printStackTrace();   }   }   System.out.println(new Date());   //這里調用壓縮方法,壓縮方法中會調用執行下載圖片的方法   zipPic(picPath,synDate,addrMap);   System.out.println(new Date());   System.out.println("----------完成--------------");   return true;  }  catch (Exception e)  {   e.printStackTrace();   //調用記錄錯誤日志的業務類   return false;  }finally {   try {   if (null != br)    br.close();   } catch (IOException e) {   e.printStackTrace();   }  }  }  /**  * 根據url地址下載圖片  * @throws IOException  */  private boolean downPic(String picPath,List<Entry<String, String>> addrList,List<File> picList)throws IOException{  InputStream is=null;  FileOutputStream fos=null;  URL url=null;  String fileName=null;  String picAddr=null;  File pic=null;  try  {   for(Map.Entry<String, String> addrEntry:addrList)   {   fileName=addrEntry.getKey();   picAddr=addrEntry.getValue();   //創建Url對象   url=new URL(picAddr);   is=url.openStream();   //URLConnection獲取到的流通過InputStream直接寫入字節數組會缺失數據,導致下載的圖片不完整,使用org.apache.commons.io.IOUtils.toByteArray(urlconnection.openstream())可以解決   byte[] bytes=IOUtils.toByteArray(is);//new byte[is.available()];獲取的字節   //流中數據讀入字節數組,讀入后,流中數據清空   pic=new File(picPath+fileName+".jpg");   fos=new FileOutputStream(pic);   fos.write(bytes);   //將下載的圖片存入List,待圖片全部下載完成后傳入zip方法進行壓縮   picList.add(pic);   fos.flush();   fos.close();   is.close();   }   return true;  }  catch (Exception e)  {   e.printStackTrace();   return false;  }  finally{   if (null!=fos)   {   fos.close();   }   if (null!=is)   {   is.close();   }  }  }  //這里是壓縮文件的偽代碼  private void zipPic(picPath,synDate,addrMap);{  //傳入需要壓縮的文件列表和壓縮文件名  ZipUtil.zipByStream(picList,new File(picPath+synDate+".zip"));  }  /**  * 創建文件  * @param path  */  private void creatFile(String path)  {  File file = new File(path);  if(!file.exists())  {   file.mkdirs();  }  } }

方法二、多線程下載、直接壓縮流

方法一雖然實現了基本功能,但是由于需要下載的圖片太多,以及壓縮本地圖片文件和刪除圖片也比較耗時,所以可以優化速度的地方有兩個。一個就是提高下載圖片的效率,一個就是提高壓縮的效率。

提高下載效率的方法可以使用多線程下載,提高壓縮效率的方法是可以不將圖片保存到本地而直接壓縮文件流。

多線程實現方式:首先我們保存了需要下載的文件的地址列表,我們要使用多線程下載就要保證不同線程下載的圖片不會重復,因此需要一個標志來區分,這時就可以使用一個索引計數器,按每個線程下載一定量圖片分割,從0開始,每隔比如400個圖片就用一個線程下載,這樣就可以確定需要的線程個數,并且每個線程下載的圖片不會重復。

壓縮文件實現方式:因為生成壓縮文件的本質也是讀取需要壓縮的文件流,然后生成壓縮包,因此我們可以不創建下載的圖片文件,而直接使用容器存儲所有線程下載的圖片流數據,然后將流數據傳給壓縮工具類直接壓縮,這樣就省略了讀取圖片文件創建流,然后生成壓縮包,再刪除本地圖片文件的繁瑣過程。

下面列出改造的主要實現:

/**  * 將下載的圖片按天壓縮  * @throws IOException  */ private boolean zipPic(String picPath,String synDate,Map<String, String> addrMap) throws IOException{  //這里由于是多線程存儲圖片流,所以需要使用線程安全的map,因此使用ConcurrentHashMap  Map<String,InputStream> pictureList=new ConcurrentHashMap<String,InputStream>();  //這里定義每個線程下載的圖片個數  int count=400;  //存儲需要下載的圖片地址  List<Entry<String, String>> addrList=new ArrayList<Entry<String, String>>(addrMap.entrySet());  //線程數,加一是因為要創建一個線程下載最后不足400個的圖片  int nThreads=(addrList.size()/count)+1;  //CountDownLatch countDownLatch = new CountDownLatch(nThreads);  try  {  boolean downPic=false;  //執行多線程下載圖片  downPic=downPic(picPath,addrList,picList,pictureList,nThreads,count);  if (downPic)  {   ZipUtil.zipByArray(picList,new File(picPath+synDate+".zip"));  }  return true;  }  catch (Exception e)  {  e.printStackTrace();  return false;  } } 

下面是創建線程池

/**  * 根據url地址下載圖片  * @throws InterruptedException  */ private boolean downPic(String picPath,List<Entry<String, String>> addrList,Map<String, byte[]> picList,Map<String, InputStream> pictureList,int nThreads,int count)throws IOException, InterruptedException{  ExecutorService threadPool=Executors.newFixedThreadPool(nThreads);  // 創建兩個個計數器  CountDownLatch begin=new CountDownLatch(0);  CountDownLatch end=new CountDownLatch(nThreads);  // 循環創建線程  for (int i = 0; i < nThreads; i++) {  List<Entry<String, String>>subAddrList=null;  // 計算每個線程執行的數據  if ((i + 1) == nThreads) {   int startIndex = (i * count);   int endIndex = addrList.size();   subAddrList = addrList.subList(startIndex, endIndex);  } else {   int startIndex = (i * count);   int endIndex = (i + 1) * count;   subAddrList = addrList.subList(startIndex, endIndex);  }  // 線程類  PicDownload mythead = new PicDownload(picPath,subAddrList,picList,pictureList);  // 這里執行線程的方式是調用線程池里的threadPool.execute(mythead)方法。  try  {   threadPool.execute(mythead);  }  catch (Exception e)  {   //記錄錯誤日志   return false;  }  }  begin.countDown();  end.await();  // 執行完關閉線程池  threadPool.shutdown();  //這里一定要循環直到線程池中所有線程都結束才能往下走,測試時由于沒有這一步導致子線程下載圖片還沒完成,而主線程已經往下走了,導致壓縮包內沒有圖片  //也可以使用CountDownLatch實現  /*while (true)  {  if (threadPool.isTerminated())  {   System.out.println("所有子線程已結束!");   break;  }  }*/  return true; } 

下面是線程實現

class PicDownload implements Runnable{  //下載圖片的地址列表  List<Entry<String, String>> addrList;  //裝載下載成功的圖片列表  Map<String, byte[]> picList;  Map<String, InputStream> pictureList;  //圖片本地存儲路徑  String picPath;   CountDownLatch begin,end;  public PicDownload(String picPath,List<Entry<String, String>> addrList,Map<String, InputStream> picList,CountDownLatch begin,CountDownLatch end){  this.addrList=addrList;  this.picList=picList;  this.picPath=picPath;  this.begin=begin;  this.end=end;  }  @Override  public void run()  {  try  {   System.out.println(Thread.currentThread().getName()+"------"+Thread.currentThread().getId());   downPicture(addrList);   //System.out.println(countDownLatch.getCount());   begin.await();  }  catch (Exception e)  {   e.printStackTrace();  }finally{   end.countDown();   //countDownLatch.countDown();  }  }  public boolean downPicture(List<Entry<String, String>> addrList) throws Exception{  InputStream is=null;  FileOutputStream fos=null;  URL url=null;  String fileName=null;  String picAddr=null;  File pic=null;  try  {   for(Map.Entry<String, String> addrEntry:addrList)   {   fileName=addrEntry.getKey();   picAddr=addrEntry.getValue();   //創建Url對象   url=new URL(picAddr);   is=url.openStream();   //URLConnection獲取到的流通過InputStream直接寫入字節數組會缺失數據,導致下載的圖片不完整,使用org.apache.commons.io.IOUtils.toByteArray(urlconnection.openstream())可以解決   //byte[] bytes=IOUtils.toByteArray(is);//new byte[is.available()];獲取的字節   //流中數據讀入字節數組,讀入后,流中數據清空   picList.put(fileName+".jpg", is);   //這時候由于沒有把流寫入文件,一定不能關閉流,否則流中的數據就會丟失   //is.close();   }   return true;  }  catch (Exception e)  {   e.printStackTrace();   return false;  }  finally{   //不能關閉流   /*if (null!=is)   {   is.close();   }*/  }  } } 

上面使用流來壓縮遇到了另一個問題,在壓縮文件時會出現java.net.SocketException:Connection reset
分析了一下原因,應該是由于流InputStream和UrlConnection是連接狀態的,UrlConnection超時重置導致了獲取輸入流失敗。

嘗試設置URLConnection的超時時間,但是測試時發現圖片下載收到網速影響較大,這種方式很不穩定,不可取,最后只有放棄使用流,而改用字節數組傳給壓縮工具類,然后將字節數組轉為流壓縮。

/** *使用容器存儲下載的圖片字節數組 */ public boolean downPicture(List<Entry<String, String>> addrList) throws Exception{  InputStream is=null;  FileOutputStream fos=null;  URL url=null;  String fileName=null;  String picAddr=null;  File pic=null;  try  {  for(Map.Entry<String, String> addrEntry:addrList)  {   fileName=addrEntry.getKey();   picAddr=addrEntry.getValue();   //創建Url對象   url=new URL(picAddr);   //打開連接,創建java.net.URLConnection對象,該對象沒有關閉連接的方法,可以轉為它的子類HttpURLConnection調用disconnect方法關閉連接。   //java.net.URLConnection和java.net.HttpURLConnection都有設置超時時間的方法關閉連接   //HttpURLConnection uc=(HttpURLConnection)url.openConnection();   is=uc.getInputStream();   //URLConnection獲取到的流通過InputStream直接寫入字節數組會缺失數據,導致下載的圖片不完整,使用org.apache.commons.io.IOUtils.toByteArray(urlconnection.openstream())可以解決   byte[] bytes=IOUtils.toByteArray(is);//new byte[is.available()];獲取的字節   //流中數據讀入字節數組,讀入后,流中數據清空   //is.read(bytes);   picList.put(fileName+".jpg",bytes);   is.close();  }  return true;  }  catch (Exception e)  {  e.printStackTrace();  return false;  }  finally{  if (null!=is)  {   is.close();  }  } }

總結:

實現過程中遇到的問題:

1、使用線程池時對于共享狀態,比如這里的存儲下載的圖片字節數據容器是所有線程共享的,因此需要使用同步的容器,否則會導致存儲的數據出問題,因此使用了ConcurrentHashMap<String,byte[]>
2、這里存在一個主線程和子線程的執行順序問題,因為主線程需要等待線程池中所有線程下載圖片結束后才能往下走去壓縮圖片,如果主線程不等待子線程結束就向下執行壓縮方法就會導致壓縮圖片缺少或者沒有壓縮圖片。因此可以使用CountDownLatch實現,或者在關閉線程池語句下面使用死循環檢查threadPool.isTerminated()才能繼續執行主線程去壓縮圖片。
3、由于直接將UrlConnection獲取到的輸入流直接傳給壓縮類進行壓縮,存在連接超時重置的情況,因此改用將下載的流存入字節數組,再傳給壓縮類壓縮,避免使用流出現意外情況。
4、在使用urlconnection.openStream()獲取輸入流后,轉換為字節數組下載的圖片是不完整的。。使用org.apache.commons.io.IOUtils.toByteArray(urlconnection.openstream())可以解決,具體可以閱讀其源碼看實現。

下面是FTP工具類的實現:

import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException;  import org.apache.commons.net.ftp.FTPClient; import org.apache.commons.net.ftp.FTPClientConfig; import org.apache.commons.net.ftp.FTPConnectionClosedException; import org.apache.commons.net.ftp.FTPReply;  public class FtpUtil2 {  private FTPClient ftpClient = null;   // ftp服務器地址  private String hostName;   // ftp服務器默認端口  public static int defaultport = 21;   // 登錄名  private String userName;   // 登錄密碼  private String password;   // 需要訪問的遠程目錄  private String remoteDir;    /**  * @param hostName  *  主機地址  * @param port  *  端口號  * @param userName  *  用戶名  * @param password  *  密碼  * @param remoteDir  *  默認工作目錄  * @param is_zhTimeZone  *  是否是中文FTP Server端  * @return  * @return  */   /**  * 新增方法  */  public FtpUtil2()  {  PropConfig config = PropConfig.loadConfig("system.properties");  String hostName = config.getConfig("ftpAddress");  String port = config.getConfig("ftpPort");  String userName = config.getConfig("ftpUserName");  String password = config.getConfig("ftpPassword");  String remoteDir = config.getConfig("remoteFilePath");  boolean is_zhTimeZone= true;  this.hostName = hostName;  this.userName = userName;  this.password = password;  this.remoteDir = remoteDir == null ? "" : remoteDir;  this.ftpClient = new FTPClient();  if (is_zhTimeZone) {   this.ftpClient.configure(FtpUtil2.Config());   this.ftpClient.setControlEncoding("GBK");  }  // 登錄  this.login();  // 切換目錄  this.changeDir(this.remoteDir);  this.setFileType(FTPClient.BINARY_FILE_TYPE);  ftpClient.setDefaultPort(Integer.parseInt(port));   }  public FtpUtil2(String hostName, int port, String userName,   String password, String remoteDir, boolean is_zhTimeZone) {  this.hostName = hostName;  this.userName = userName;  this.password = password;  defaultport=port;  this.remoteDir = remoteDir == null ? "" : remoteDir;  this.ftpClient = new FTPClient();  if (is_zhTimeZone) {   this.ftpClient.configure(FtpUtil2.Config());   this.ftpClient.setControlEncoding("GBK");   }  // 登錄  this.login();  // 切換目錄  this.changeDir(this.remoteDir);  this.setFileType(FTPClient.ASCII_FILE_TYPE);  ftpClient.setDefaultPort(port);   }   /**  * 登錄FTP服務器  */  public boolean login() {  boolean success = false;  try {   ftpClient.connect(this.hostName,defaultport);   ftpClient.login(this.userName, this.password);   int reply;   reply = ftpClient.getReplyCode();   if (!FTPReply.isPositiveCompletion(reply)) {   ftpClient.disconnect();   return success;   }  } catch (FTPConnectionClosedException e) {   // TODO Auto-generated catch block   e.printStackTrace();  } catch (IOException e) {   // TODO Auto-generated catch block   e.printStackTrace();  }  success = true;  System.out.println("連接到ftp服務器:" + this.hostName + " 成功..開始登錄");  return success;  }   private static FTPClientConfig Config() {  FTPClientConfig conf = new FTPClientConfig(FTPClientConfig.SYST_UNIX);  conf.setRecentDateFormatStr("MM月dd日 HH:mm");  // conf.setRecentDateFormatStr("(YYYY年)?MM月dd日( HH:mm)?");  return conf;  }   /**  * 變更工作目錄  *  * @param remoteDir  *  */  public void changeDir(String remoteDir) {  try {   this.remoteDir = remoteDir;   ftpClient.changeWorkingDirectory(remoteDir);  } catch (IOException e) {   // TODO Auto-generated catch block   e.printStackTrace();  }  System.out.println("變更工作目錄為:" + remoteDir);  }   /**  * 返回上一級目錄(父目錄)  */  public void toParentDir() {  try {   ftpClient.changeToParentDirectory();  } catch (IOException e) {   // TODO Auto-generated catch block   e.printStackTrace();  }  }   /**  * 列出當前工作目錄下所有文件  */  public String[] ListAllFiles() {  String[] names = this.ListFiles("*");  return this.sort(names);  }   /**  * 列出指定工作目錄下的匹配文件  *  * @param dir  *  exp: /cim/  * @param file_regEx  *  通配符為*  */  public String[] ListAllFiles(String dir, String file_regEx) {  String[] names = this.ListFiles(dir + file_regEx);  return this.sort(names);  }   /**  * 列出匹配文件  *  * @param file_regEx  *  匹配字符,通配符為*  */  public String[] ListFiles(String file_regEx) {  try {   /**    * FTPFile[] remoteFiles = ftpClient.listFiles(file_regEx);    * //System.out.println(remoteFiles.length); String[] name = new    * String[remoteFiles.length]; if(remoteFiles != null) { for(int    * i=0;i<remoteFiles.length;i++) { if(remoteFiles[i] == null)    * name[i] = ""; else    * if(remoteFiles[i].getName()==null||remoteFiles    * [i].getName().equals    * (".")||remoteFiles[i].getName().equals("..")) { name[i] = "";    * } else name[i] = remoteFiles[i].getName();    * System.out.println(name[i]); } }    */   ftpClient.enterLocalPassiveMode();   String[] name = ftpClient.listNames(file_regEx);;   if (name == null)   return new String[0];    return this.sort(name);   } catch (Exception e) {   // TODO Auto-generated catch block   e.printStackTrace();  }  return new String[0];  }   public void Lists(String reg) {  try {   String[] a = ftpClient.listNames(reg);   if (a != null) {   for (String b : a) {    System.out.println(b);   }   }  } catch (IOException e) {   // TODO Auto-generated catch block   e.printStackTrace();  }  }   /**  * 設置傳輸文件的類型[文本文件或者二進制文件]  *  * @param fileType  *  --BINARY_FILE_TYPE,ASCII_FILE_TYPE  */  public void setFileType(int fileType) {  try {   ftpClient.setFileType(fileType);  } catch (IOException e) {   e.printStackTrace();  }  }   /**  * 上傳文件  *  * @param localFilePath  *  --本地文件路徑+文件名  * @param newFileName  *  --新的文件名  */  public void uploadFile(String localFilePath, String newFileName) {  // 上傳文件  this.ftpClient.enterLocalPassiveMode();// 被動模式連接  BufferedInputStream buffIn = null;  try {   buffIn = new BufferedInputStream(new FileInputStream(localFilePath));   boolean ifUpload = ftpClient.storeFile(newFileName, buffIn);   if (!ifUpload) {   System.out.println("上傳文件失敗。。。");   } else {   System.out.println("上傳文件成功。。。");   }  } catch (Exception e) {   e.printStackTrace();  } finally {   try {   if (buffIn != null)    buffIn.close();   } catch (Exception e) {   e.printStackTrace();   }  }  }   /**  * 上傳文件2  *  * @param file  *  --FileInputStream的文件  * @param newFileName  *  --新的文件名  */  public void newUploadFile(FileInputStream file, String newFileName) {  // 上傳文件  this.ftpClient.enterLocalPassiveMode();// 被動模式連接  BufferedInputStream buffIn = null;  try {   buffIn = new BufferedInputStream(file);   boolean ifUpload = ftpClient.storeFile(newFileName, buffIn);   if (!ifUpload) {   System.out.println("上傳文件失敗。。。");   } else {   System.out.println("上傳文件成功。。。");   }  } catch (Exception e) {   e.printStackTrace();  } finally {   try {   if (buffIn != null)    buffIn.close();   } catch (Exception e) {   e.printStackTrace();   }  }  }   /**  * 下載文件(單個)  *  * @param remoteFileName  *  --服務器上的文件名  * @param localFileName  *  --本地文件名  */  public boolean downloadFile(String remoteFileName, String localFileName) {  this.ftpClient.enterLocalPassiveMode();// 被動模式連接  BufferedOutputStream buffOut = null;  try {   buffOut = new BufferedOutputStream(new FileOutputStream(    localFileName));   boolean ifDownload = ftpClient    .retrieveFile(remoteFileName, buffOut);   if (!ifDownload) {   System.out.println("下載文件失敗。。。");   return false;   } else {   System.out.println("下載文件成功。。。");   }  } catch (Exception e) {   e.printStackTrace();   return false;  } finally {   try {   if (buffOut != null)    buffOut.close();   } catch (Exception e) {   e.printStackTrace();   }  }  return true;  }   /**  * 關閉FTP連接  */  public void close() {  try {   if (ftpClient != null) {   ftpClient.logout();   ftpClient.disconnect();   }  } catch (Exception e) {   e.printStackTrace();  }  }   /**  * 冒泡排序字符串(從大到小)  */  public String[] sort(String[] str_Array) {  if (str_Array == null) {   throw new NullPointerException("The str_Array can not be null!");  }  String tmp = "";  for (int i = 0; i < str_Array.length; i++) {   for (int j = 0; j < str_Array.length - i - 1; j++) {   if (str_Array[j].compareTo(str_Array[j + 1]) < 0) {    tmp = str_Array[j];    str_Array[j] = str_Array[j + 1];    str_Array[j + 1] = tmp;   }   }  }  return str_Array;  }   public static void main(String[] strs) {  FtpUtil2 FtpUtil2 = new FtpUtil2("192.168.1.112", 20011, "test1",   "test1", "/", true);  FtpUtil2.downloadFile("test.txt", "d://test.txt");  }  } 

下面是ZIP工具類:

import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.Enumeration; import java.util.List; import java.util.Map; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import java.util.zip.ZipOutputStream;  import org.apache.commons.io.IOUtils;  import com.ibatis.common.logging.Log; import com.ibatis.common.logging.LogFactory;  public class ZipUtil {  private static final Log log = LogFactory.getLog(ZipUtil.class);    /**  * 壓縮文件  *  * @param srcfile File[] 需要壓縮的文件列表  * @param zipfile File 壓縮后的文件  */  public static OutputStream zipFiles(List<File> srcfile, OutputStream outputStream) {  byte[] buf = new byte[1024];  try {      // Create the ZIP file   ZipOutputStream out = new ZipOutputStream(outputStream);   // Compress the files   for (int i = 0; i < srcfile.size(); i++) {   File file = srcfile.get(i);   FileInputStream in = new FileInputStream(file);   // Add ZIP entry to output stream.   out.putNextEntry(new ZipEntry(file.getName()));      // Transfer bytes from the file to the ZIP file   int len;   while ((len = in.read(buf)) > 0) {    //System.out.println(len+"==============");       out.write(buf, 0, len);   }   // Complete the entry   out.closeEntry();   in.close();   }   // Complete the ZIP file   out.close();  } catch (IOException e) {   log.error("ZipUtil zipFiles exception:"+e);  }  return outputStream;  }    /**  * 壓縮文件  *  * @param srcfile File[] 需要壓縮的文件列表  * @param zipfile File 壓縮后的文件  */  public static void zipFiles(List<File> srcfile, File zipfile) {  byte[] buf = new byte[1024];  try {   // Create the ZIP file   ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipfile));   // Compress the files   for (int i = 0; i < srcfile.size(); i++) {   File file = srcfile.get(i);   FileInputStream in = new FileInputStream(file);   // Add ZIP entry to output stream.   out.putNextEntry(new ZipEntry(file.getName()));   // Transfer bytes from the file to the ZIP file   int len;   while ((len = in.read(buf)) > 0) {    out.write(buf, 0, len);   }   // Complete the entry   out.closeEntry();   in.close();   }   // Complete the ZIP file   out.close();  } catch (IOException e) {   log.error("ZipUtil zipFiles exception:"+e);  }  }    /**  * 壓縮文件  * srcfile:key:文件名,value:文件對應的輸入流  * @param srcfile  * @param zipfile  * @see  */  public static void zipByStream(Map<String,InputStream> srcfile, File zipfile) {  try {   // Create the ZIP file   ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipfile));   // Compress the files   System.out.println(srcfile.entrySet().size());   for (Map.Entry<String, InputStream> fileEntry:srcfile.entrySet()) {   InputStream in = fileEntry.getValue();   // Add ZIP entry to output stream.   System.out.println(in.available());   out.putNextEntry(new ZipEntry(fileEntry.getKey()));   // Transfer bytes from the file to the ZIP file   byte[] bytes=IOUtils.toByteArray(in);   out.write(bytes);   out.closeEntry();   in.close();   }   // Complete the ZIP file   out.close();  } catch (IOException e) {   log.error("ZipUtil zipFiles exception:"+e);   System.out.println(e.getMessage());  }  }    /**  * 壓縮文件  * srcfile:key:文件名,value:文件對應的字節數組  * @param srcfile  * @param zipfile  * @see  */  public static void zipByArray(Map<String,byte[]> srcfile, File zipfile) {  byte[] buf = new byte[1024];  try {   // Create the ZIP file   ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipfile));   // Compress the files   System.out.println(srcfile.entrySet().size());   for (Map.Entry<String, byte[]> fileEntry:srcfile.entrySet()) {   //InputStream in = fileEntry.getValue();   // Add ZIP entry to output stream.   out.putNextEntry(new ZipEntry(fileEntry.getKey()));   // Transfer bytes from the file to the ZIP file   byte[] bytes=fileEntry.getValue();//IOUtils.toByteArray(in);   out.write(bytes);   out.closeEntry();   //in.close();   }   // Complete the ZIP file   out.close();  } catch (IOException e) {   log.error("ZipUtil zipFiles exception:"+e);   System.out.println(e.getMessage());  }  }   /**  * 解壓縮  *  * @param zipfile File 需要解壓縮的文件  * @param descDir String 解壓后的目標目錄  */  public static void unZipFiles(File zipfile, String descDir) {  try {   // Open the ZIP file   ZipFile zf = new ZipFile(zipfile);   for (Enumeration entries = zf.entries(); entries.hasMoreElements();) {   // Get the entry name   ZipEntry entry = ((ZipEntry) entries.nextElement());   String zipEntryName = entry.getName();   InputStream in = zf.getInputStream(entry);   // System.out.println(zipEntryName);   OutputStream out = new FileOutputStream(descDir + zipEntryName);   byte[] buf1 = new byte[1024];   int len;   while ((len = in.read(buf1)) > 0) {    out.write(buf1, 0, len);   }   // Close the file and stream   in.close();   out.close();   }  } catch (IOException e) {   log.error("ZipUtil unZipFiles exception:"+e);  }  }   /**  * Main  *  * @param args  */  public static void main(String[] args) {  List<File> srcfile=new ArrayList<File>();  srcfile.add(new File("d://1.jpg"));  srcfile.add(new File("d://2.jpg"));  srcfile.add(new File("d://3.jpg"));  srcfile.add(new File("d://4.jpg"));  File zipfile = new File("d://pic.zip");  ZipUtil.zipFiles(srcfile, zipfile);  } } 

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VeVb武林網。


注:相關教程知識閱讀請移步到JAVA教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
97涩涩爰在线观看亚洲| 亚洲精品成人网| 欧美精品性视频| 国产亚洲精品综合一区91| 91免费高清视频| 日韩精品在线免费观看| 日韩欧美aaa| 久久97久久97精品免视看| 国产91免费观看| 色综合视频一区中文字幕| 亚洲精品一区二区网址| 亚洲精品国产电影| 精品亚洲一区二区三区在线观看| 色狠狠av一区二区三区香蕉蜜桃| 一区二区三区四区精品| 欧美视频一区二区三区…| 久久成人免费视频| 日韩中文字幕网站| 日韩免费观看网站| 欧美国产日韩一区二区在线观看| 久久久免费观看| 午夜精品久久久久久久久久久久| 77777少妇光屁股久久一区| 中文字幕亚洲欧美| 精品福利樱桃av导航| 亚洲va欧美va国产综合久久| 亚洲精品之草原avav久久| 亚洲老头同性xxxxx| 尤物99国产成人精品视频| 国产不卡av在线免费观看| 国产美女扒开尿口久久久| 亚洲日韩中文字幕在线播放| 亚洲欧美国产日韩中文字幕| 亚洲网站在线看| 国产午夜精品全部视频在线播放| 久久99国产精品自在自在app| 欧美激情国产日韩精品一区18| 精品亚洲男同gayvideo网站| 国产精品嫩草视频| 欧美日韩亚洲天堂| 中文字幕精品av| 色樱桃影院亚洲精品影院| 北条麻妃一区二区在线观看| 97在线视频免费播放| 中文字幕欧美视频在线| 色婷婷综合久久久久| 亚洲丝袜在线视频| 国内精品一区二区三区四区| 亚洲成人黄色网| 日韩精品极品视频免费观看| 亚洲精选一区二区| 国产精品亚洲网站| 中文字幕综合一区| 情事1991在线| 欧美大尺度激情区在线播放| 国产精品黄色影片导航在线观看| 亚洲国产欧美一区二区三区久久| 日韩福利在线播放| 欧美成人精品不卡视频在线观看| 久久久精品2019中文字幕神马| 在线亚洲国产精品网| 亚洲三级免费看| 欧洲午夜精品久久久| 久久精品一偷一偷国产| 岛国精品视频在线播放| 国产视频欧美视频| 亚洲第一视频网| 97精品视频在线| 欧美肥臀大乳一区二区免费视频| 国内外成人免费激情在线视频| 日韩a**站在线观看| 亚洲美女又黄又爽在线观看| 一本大道亚洲视频| 亚洲综合日韩在线| 亚洲第一av在线| 亚洲va欧美va国产综合剧情| 成人日韩在线电影| 激情懂色av一区av二区av| 永久555www成人免费| 欧美黑人国产人伦爽爽爽| 久久夜色精品国产亚洲aⅴ| 国产成人在线精品| 久久久久久国产| 亚洲xxxxx| 久久av中文字幕| 欧美大尺度在线观看| 国产小视频91| 91免费看国产| 国产精品亚洲视频在线观看| 亚洲久久久久久久久久久| 亚洲欧美精品suv| 综合国产在线观看| 最近2019年好看中文字幕视频| 国产精品久久97| 久久久免费高清电视剧观看| 狠狠综合久久av一区二区小说| 精品福利樱桃av导航| 国产精品海角社区在线观看| 米奇精品一区二区三区在线观看| 秋霞午夜一区二区| 亚洲视频在线观看视频| 国产免费一区二区三区在线观看| 日韩国产中文字幕| 欧美成人激情在线| 亚洲天堂男人天堂女人天堂| 久久精品一区中文字幕| 青青青国产精品一区二区| 欧美最顶级丰满的aⅴ艳星| 高跟丝袜一区二区三区| 午夜精品蜜臀一区二区三区免费| 国产精品吹潮在线观看| 日韩欧美在线视频日韩欧美在线视频| 成人黄色在线免费| 91在线免费视频| 国产欧美精品va在线观看| 69**夜色精品国产69乱| 国产美女主播一区| 97激碰免费视频| 欧美日韩久久久久| 国产精品久久久久久久久久久不卡| 亚洲乱码一区av黑人高潮| 中文字幕欧美亚洲| 韩剧1988在线观看免费完整版| 色综合天天综合网国产成人网| 91热精品视频| 色悠悠国产精品| 热re99久久精品国产66热| 91国内免费在线视频| 国产精品视频自拍| 精品日韩视频在线观看| 国内精品久久影院| 乱亲女秽乱长久久久| 亚洲国产一区自拍| 亚洲第一区中文99精品| 亚洲欧美色婷婷| 精品国产乱码久久久久久天美| 成人乱人伦精品视频在线观看| www.亚洲一区| 欧美性xxxx极品hd满灌| 亚洲热线99精品视频| 欧美成人精品激情在线观看| 国产精品专区一| 国产男女猛烈无遮挡91| 亚洲视频一区二区三区| 国产在线精品自拍| 国产精品成人在线| 国产91在线播放九色快色| 欧美裸身视频免费观看| 97国产成人精品视频| 日本19禁啪啪免费观看www| 欧美激情网友自拍| 久久精品中文字幕电影| 国产精品日韩欧美| 国产成+人+综合+亚洲欧美丁香花| 亚洲一区二区久久久久久久| 91亚洲精品一区| 欧美性猛交xxxx黑人猛交| 91久久精品久久国产性色也91| 777午夜精品福利在线观看| xvideos成人免费中文版| 日韩欧美在线字幕| 欧美日韩性生活视频| 欧美激情aaaa| 欧美在线影院在线视频|