欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

java多線程實(shí)現(xiàn)下載圖片并壓縮

 更新時間:2018年05月15日 15:41:17   作者:Terisadeng  
這篇文章主要為大家詳細(xì)介紹了java多線程實(shí)現(xiàn)下載圖片并壓縮,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

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

使用框架:SpringMVC

定時任務(wù)實(shí)現(xiàn):繼承org.springframework.scheduling.quartz.QuartzJobBean;

ftp環(huán)境搭建就不說了,在其他博客記錄過,使用虛擬機(jī)中的CentOS搭建的FTP服務(wù),創(chuàng)建FTP賬號及對應(yīng)目錄,事先上傳需要下載的圖片地址文件。文件內(nèi)容格式“圖片ID||圖片地址”。

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

public class PictureTransferJob extends QuartzJobBean 
{ 
 protected void executeInternal(JobExecutionContext arg0) throws JobExecutionException 
 { 
 //實(shí)際的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"; 
 //實(shí)際下載的圖片存儲目錄 
 String picPath=path.substring(1, path.indexOf("WEB-INF/classes"))+"pic"; 
 addrPath = addrPath.replace("%20"," "); 
 picPath = picPath.replace("%20"," "); 
 try 
 { 
 //創(chuàng)建存儲圖片地址的文件 
 creatFile(addrPath); 
 //創(chuàng)建存儲實(shí)際圖片的文件 
 creatFile(picPath); 
 String oldAddrPath = addrPath; 
 String oldPicPath = picPath; 
 //創(chuàng)建FTP連接 
 FtpUtil2 ftpUtil2 = new FtpUtil2(hostName, port,userName, password, ftpDowload, true); 
 //遍歷FTP目錄下的文件 
 String[] files = ftpUtil2.ListAllFiles(); 
 //本地?cái)?shù)據(jù)庫會有一個表記錄下載過的文件,這里會查詢數(shù)據(jù)庫和ftp列出的文件名比較,如果已經(jīng)下載過的文件就不會下載,避免重復(fù)下載。 
 //下面省略比較的過程,循環(huán)files數(shù)組,在本地創(chuàng)建文件 
 for(int i=0;i<files.length;i++){ 
 creatFile(addrPath+File.separator+fileName); 
 //ftpDowload是ftp服務(wù)器存儲文件的地址,addrPath是本地存儲文件的地址 
 //這里一個返回狀態(tài)判斷文件是否下載成功 
 boolean downloadInvestorFlag = ftpUtil2.downloadFile(ftpDowload, addrPath); 
 //文件下載成功后調(diào)讀取文件的方法,將需要下載的圖片地址存入容器 
 boolean entityState = setPictureDetail(addrPath,picPath,fileNameDate); 
 } 
 }  
 catch (Exception e) 
 { 
  e.printStackTrace(); 
  //調(diào)記錄錯誤日志的業(yè)務(wù)類用于發(fā)送下載文件出錯的短信 
 } 
} 
  
//這里開始讀圖片地址 
private boolean setPictureDetail(String addrPath,String picPath,String synDate) 
{ 
 System.out.println("----------進(jìn)入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()); 
  //這里調(diào)用壓縮方法,壓縮方法中會調(diào)用執(zhí)行下載圖片的方法 
  zipPic(picPath,synDate,addrMap); 
  System.out.println(new Date()); 
  System.out.println("----------完成--------------"); 
  return true; 
 } 
 catch (Exception e) 
 { 
  e.printStackTrace(); 
  //調(diào)用記錄錯誤日志的業(yè)務(wù)類 
  return false; 
 }finally { 
  try { 
  if (null != br) 
   br.close(); 
  } catch (IOException e) { 
  e.printStackTrace(); 
  } 
 } 
 } 
 /** 
 * 根據(jù)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(); 
  //創(chuàng)建Url對象 
  url=new URL(picAddr); 
  is=url.openStream(); 
  //URLConnection獲取到的流通過InputStream直接寫入字節(jié)數(shù)組會缺失數(shù)據(jù),導(dǎo)致下載的圖片不完整,使用org.apache.commons.io.IOUtils.toByteArray(urlconnection.openstream())可以解決 
  byte[] bytes=IOUtils.toByteArray(is);//new byte[is.available()];獲取的字節(jié) 
  //流中數(shù)據(jù)讀入字節(jié)數(shù)組,讀入后,流中數(shù)據(jù)清空 
  pic=new File(picPath+fileName+".jpg"); 
  fos=new FileOutputStream(pic); 
  fos.write(bytes); 
  //將下載的圖片存入List,待圖片全部下載完成后傳入zip方法進(jìn)行壓縮 
  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")); 
 } 
 /** 
 * 創(chuàng)建文件 
 * @param path 
 */ 
 private void creatFile(String path) 
 { 
 File file = new File(path); 
 if(!file.exists()) 
 { 
  file.mkdirs(); 
 } 
 } 
}

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

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

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

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

壓縮文件實(shí)現(xiàn)方式:因?yàn)樯蓧嚎s文件的本質(zhì)也是讀取需要壓縮的文件流,然后生成壓縮包,因此我們可以不創(chuàng)建下載的圖片文件,而直接使用容器存儲所有線程下載的圖片流數(shù)據(jù),然后將流數(shù)據(jù)傳給壓縮工具類直接壓縮,這樣就省略了讀取圖片文件創(chuàng)建流,然后生成壓縮包,再刪除本地圖片文件的繁瑣過程。

下面列出改造的主要實(shí)現(xiàn):

/** 
 * 將下載的圖片按天壓縮 
 * @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>(); 
 //這里定義每個線程下載的圖片個數(shù) 
 int count=400; 
 //存儲需要下載的圖片地址 
 List<Entry<String, String>> addrList=new ArrayList<Entry<String, String>>(addrMap.entrySet()); 
 //線程數(shù),加一是因?yàn)橐獎?chuàng)建一個線程下載最后不足400個的圖片 
 int nThreads=(addrList.size()/count)+1; 
 //CountDownLatch countDownLatch = new CountDownLatch(nThreads); 
 try 
 { 
 boolean downPic=false; 
 //執(zhí)行多線程下載圖片 
 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; 
 } 
} 

下面是創(chuàng)建線程池

/** 
 * 根據(jù)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); 
 // 創(chuàng)建兩個個計(jì)數(shù)器 
 CountDownLatch begin=new CountDownLatch(0); 
 CountDownLatch end=new CountDownLatch(nThreads); 
 // 循環(huán)創(chuàng)建線程 
 for (int i = 0; i < nThreads; i++) { 
 List<Entry<String, String>>subAddrList=null; 
 // 計(jì)算每個線程執(zhí)行的數(shù)據(jù) 
 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); 
 // 這里執(zhí)行線程的方式是調(diào)用線程池里的threadPool.execute(mythead)方法。 
 try 
 { 
  threadPool.execute(mythead); 
 } 
 catch (Exception e) 
 { 
  //記錄錯誤日志 
  return false; 
 } 
 } 
 begin.countDown(); 
 end.await(); 
 // 執(zhí)行完關(guān)閉線程池 
 threadPool.shutdown(); 
 //這里一定要循環(huán)直到線程池中所有線程都結(jié)束才能往下走,測試時由于沒有這一步導(dǎo)致子線程下載圖片還沒完成,而主線程已經(jīng)往下走了,導(dǎo)致壓縮包內(nèi)沒有圖片 
 //也可以使用CountDownLatch實(shí)現(xiàn) 
 /*while (true) 
 { 
 if (threadPool.isTerminated()) 
 { 
  System.out.println("所有子線程已結(jié)束!"); 
  break; 
 } 
 }*/ 
 return true; 
} 

下面是線程實(shí)現(xiàn)

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(); 
  //創(chuàng)建Url對象 
  url=new URL(picAddr); 
  is=url.openStream(); 
  //URLConnection獲取到的流通過InputStream直接寫入字節(jié)數(shù)組會缺失數(shù)據(jù),導(dǎo)致下載的圖片不完整,使用org.apache.commons.io.IOUtils.toByteArray(urlconnection.openstream())可以解決 
  //byte[] bytes=IOUtils.toByteArray(is);//new byte[is.available()];獲取的字節(jié) 
  //流中數(shù)據(jù)讀入字節(jié)數(shù)組,讀入后,流中數(shù)據(jù)清空 
  picList.put(fileName+".jpg", is); 
  //這時候由于沒有把流寫入文件,一定不能關(guān)閉流,否則流中的數(shù)據(jù)就會丟失 
  //is.close(); 
  } 
  return true; 
 } 
 catch (Exception e) 
 { 
  e.printStackTrace(); 
  return false; 
 } 
 finally{ 
  //不能關(guān)閉流 
  /*if (null!=is) 
  { 
  is.close(); 
  }*/ 
 } 
 } 
} 

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

嘗試設(shè)置URLConnection的超時時間,但是測試時發(fā)現(xiàn)圖片下載收到網(wǎng)速影響較大,這種方式很不穩(wěn)定,不可取,最后只有放棄使用流,而改用字節(jié)數(shù)組傳給壓縮工具類,然后將字節(jié)數(shù)組轉(zhuǎn)為流壓縮。

/** 
*使用容器存儲下載的圖片字節(jié)數(shù)組 
*/ 
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(); 
  //創(chuàng)建Url對象 
  url=new URL(picAddr); 
  //打開連接,創(chuàng)建java.net.URLConnection對象,該對象沒有關(guān)閉連接的方法,可以轉(zhuǎn)為它的子類HttpURLConnection調(diào)用disconnect方法關(guān)閉連接。 
  //java.net.URLConnection和java.net.HttpURLConnection都有設(shè)置超時時間的方法關(guān)閉連接 
  //HttpURLConnection uc=(HttpURLConnection)url.openConnection(); 
  is=uc.getInputStream(); 
  //URLConnection獲取到的流通過InputStream直接寫入字節(jié)數(shù)組會缺失數(shù)據(jù),導(dǎo)致下載的圖片不完整,使用org.apache.commons.io.IOUtils.toByteArray(urlconnection.openstream())可以解決 
  byte[] bytes=IOUtils.toByteArray(is);//new byte[is.available()];獲取的字節(jié) 
  //流中數(shù)據(jù)讀入字節(jié)數(shù)組,讀入后,流中數(shù)據(jù)清空 
  //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(); 
 } 
 } 
}

總結(jié):

實(shí)現(xiàn)過程中遇到的問題:

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

下面是FTP工具類的實(shí)現(xiàn):

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服務(wù)器地址 
 private String hostName; 
 
 // ftp服務(wù)器默認(rèn)端口 
 public static int defaultport = 21; 
 
 // 登錄名 
 private String userName; 
 
 // 登錄密碼 
 private String password; 
 
 // 需要訪問的遠(yuǎn)程目錄 
 private String remoteDir; 
 
 
 /** 
 * @param hostName 
 *  主機(jī)地址 
 * @param port 
 *  端口號 
 * @param userName 
 *  用戶名 
 * @param password 
 *  密碼 
 * @param remoteDir 
 *  默認(rèn)工作目錄 
 * @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服務(wù)器 
 */ 
 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服務(wù)器:" + 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(); 
 } 
 } 
 
 /** 
 * 列出當(dāng)前工作目錄下所有文件 
 */ 
 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(); 
 } 
 } 
 
 /** 
 * 設(shè)置傳輸文件的類型[文本文件或者二進(jìn)制文件] 
 * 
 * @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 
 *  --服務(wù)器上的文件名 
 * @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; 
 } 
 
 /** 
 * 關(guān)閉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:文件對應(yīng)的輸入流 
 * @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:文件對應(yīng)的字節(jié)數(shù)組 
 * @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 解壓后的目標(biāo)目錄 
 */ 
 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); 
 } 
} 

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • 詳解基于java的Socket聊天程序——客戶端(附demo)

    詳解基于java的Socket聊天程序——客戶端(附demo)

    這篇文章主要介紹了詳解基于java的Socket聊天程序——客戶端(附demo),客戶端設(shè)計(jì)主要分成兩個部分,分別是socket通訊模塊設(shè)計(jì)和UI相關(guān)設(shè)計(jì)。有興趣的可以了解一下。
    2016-12-12
  • feign服務(wù)端發(fā)現(xiàn)異??蛻舳颂幚淼姆椒ń榻B

    feign服務(wù)端發(fā)現(xiàn)異常客戶端處理的方法介紹

    這篇文章主要給大家介紹了關(guān)于feign服務(wù)端發(fā)現(xiàn)異??蛻舳颂幚淼姆椒ǎ闹型ㄟ^示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用feign具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-07-07
  • mybatis連接數(shù)據(jù)庫實(shí)現(xiàn)雙表查詢

    mybatis連接數(shù)據(jù)庫實(shí)現(xiàn)雙表查詢

    本文主要介紹了mybatis連接數(shù)據(jù)庫實(shí)現(xiàn)雙表查詢,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-09-09
  • Java基于elasticsearch實(shí)現(xiàn)集群管理

    Java基于elasticsearch實(shí)現(xiàn)集群管理

    這篇文章主要介紹了java基于elasticsearch實(shí)現(xiàn)集群管理,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-02-02
  • Java身份證驗(yàn)證方法實(shí)例詳解

    Java身份證驗(yàn)證方法實(shí)例詳解

    這篇文章主要介紹了Java身份證驗(yàn)證方法實(shí)例詳解的相關(guān)資料,需要的朋友可以參考下
    2017-04-04
  • zuul過濾器中轉(zhuǎn)發(fā)請求頭的解決方案

    zuul過濾器中轉(zhuǎn)發(fā)請求頭的解決方案

    這篇文章主要介紹了zuul過濾器中轉(zhuǎn)發(fā)請求頭的解決方案,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • ElasticSearch學(xué)習(xí)之Es集群Api操作示例

    ElasticSearch學(xué)習(xí)之Es集群Api操作示例

    這篇文章主要為大家介紹了ElasticSearch學(xué)習(xí)之Es集群Api操作示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-01-01
  • Spring在@ConditionalOnProperty注解使用詳解

    Spring在@ConditionalOnProperty注解使用詳解

    這篇文章主要介紹了Spring在@ConditionalOnProperty注解使用詳解,@ConditionalOnProperty注解是Spring Boot的條件注解,主要用法是根據(jù)配置文件中的屬性來控制某個配置類是否生效,或者控制某個Bean是否被創(chuàng)建,需要的朋友可以參考下
    2023-11-11
  • SpringCloud Stream使用解析

    SpringCloud Stream使用解析

    這篇文章主要介紹了SpringCloud Stream介紹,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-03-03
  • Java AQS信號量Semaphore的使用

    Java AQS信號量Semaphore的使用

    Semaphore來自于JDK1.5的JUC包,直譯過來就是信號量,被作為一種多線程并發(fā)控制工具來使用。本文將詳解其原理與使用方法,感興趣的可以學(xué)習(xí)一下
    2023-02-02

最新評論