這篇文章給大家介紹怎么在java中利用多線程下載圖片并壓縮,內(nèi)容非常詳細(xì),感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。
成都創(chuàng)新互聯(lián)是一家專注于網(wǎng)站制作、成都做網(wǎng)站與策劃設(shè)計,嫩江網(wǎng)站建設(shè)哪家好?成都創(chuàng)新互聯(lián)做網(wǎng)站,專注于網(wǎng)站建設(shè)10多年,網(wǎng)設(shè)計領(lǐng)域的專業(yè)建站公司;建站業(yè)務(wù)涵蓋:嫩江等地區(qū)。嫩江做網(wǎng)站價格咨詢:13518219792
使用框架:SpringMVC
定時任務(wù)實現(xiàn):繼承org.springframework.scheduling.quartz.QuartzJobBean;
ftp環(huán)境搭建就不說了,在其他博客記錄過,使用虛擬機(jī)中的CentOS搭建的FTP服務(wù),創(chuàng)建FTP賬號及對應(yīng)目錄,事先上傳需要下載的圖片地址文件。文件內(nèi)容格式“圖片ID||圖片地址”。
方法一、最簡單的實現(xiàn)方法就是先下載存儲圖片url地址的文件,然后讀取文件遍歷圖片地址,調(diào)下載圖片的方法將圖片存儲到本地,最后壓縮下載的圖片,完成后刪除下載的圖片,只保留壓縮包。
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 { //創(chuàng)建存儲圖片地址的文件 creatFile(addrPath); //創(chuàng)建存儲實際圖片的文件 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(); //本地數(shù)據(jù)庫會有一個表記錄下載過的文件,這里會查詢數(shù)據(jù)庫和ftp列出的文件名比較,如果已經(jīng)下載過的文件就不會下載,避免重復(fù)下載。 //下面省略比較的過程,循環(huán)files數(shù)組,在本地創(chuàng)建文件 for(int i=0;i服務(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 addrMap=new HashMap (); 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 > addrList,List 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 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(); } } }
方法二、多線程下載、直接壓縮流
方法一雖然實現(xiàn)了基本功能,但是由于需要下載的圖片太多,以及壓縮本地圖片文件和刪除圖片也比較耗時,所以可以優(yōu)化速度的地方有兩個。一個就是提高下載圖片的效率,一個就是提高壓縮的效率。
提高下載效率的方法可以使用多線程下載,提高壓縮效率的方法是可以不將圖片保存到本地而直接壓縮文件流。
多線程實現(xiàn)方式:首先我們保存了需要下載的文件的地址列表,我們要使用多線程下載就要保證不同線程下載的圖片不會重復(fù),因此需要一個標(biāo)志來區(qū)分,這時就可以使用一個索引計數(shù)器,按每個線程下載一定量圖片分割,從0開始,每隔比如400個圖片就用一個線程下載,這樣就可以確定需要的線程個數(shù),并且每個線程下載的圖片不會重復(fù)。
壓縮文件實現(xiàn)方式:因為生成壓縮文件的本質(zhì)也是讀取需要壓縮的文件流,然后生成壓縮包,因此我們可以不創(chuàng)建下載的圖片文件,而直接使用容器存儲所有線程下載的圖片流數(shù)據(jù),然后將流數(shù)據(jù)傳給壓縮工具類直接壓縮,這樣就省略了讀取圖片文件創(chuàng)建流,然后生成壓縮包,再刪除本地圖片文件的繁瑣過程。
下面列出改造的主要實現(xiàn):
/** * 將下載的圖片按天壓縮 * @throws IOException */ private boolean zipPic(String picPath,String synDate,MapaddrMap) throws IOException{ //這里由于是多線程存儲圖片流,所以需要使用線程安全的map,因此使用ConcurrentHashMap Map pictureList=new ConcurrentHashMap (); //這里定義每個線程下載的圖片個數(shù) int count=400; //存儲需要下載的圖片地址 List > addrList=new ArrayList >(addrMap.entrySet()); //線程數(shù),加一是因為要創(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> addrList,Map picList,Map pictureList,int nThreads,int count)throws IOException, InterruptedException{ ExecutorService threadPool=Executors.newFixedThreadPool(nThreads); // 創(chuàng)建兩個個計數(shù)器 CountDownLatch begin=new CountDownLatch(0); CountDownLatch end=new CountDownLatch(nThreads); // 循環(huán)創(chuàng)建線程 for (int i = 0; i < nThreads; i++) { List >subAddrList=null; // 計算每個線程執(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實現(xiàn) /*while (true) { if (threadPool.isTerminated()) { System.out.println("所有子線程已結(jié)束!"); break; } }*/ return true; }
下面是線程實現(xiàn)
class PicDownload implements Runnable{ //下載圖片的地址列表 List> addrList; //裝載下載成功的圖片列表 Map picList; Map pictureList; //圖片本地存儲路徑 String picPath; CountDownLatch begin,end; public PicDownload(String picPath,List > addrList,Map 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 > 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 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> 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 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é):
實現(xiàn)過程中遇到的問題:
1、使用線程池時對于共享狀態(tài),比如這里的存儲下載的圖片字節(jié)數(shù)據(jù)容器是所有線程共享的,因此需要使用同步的容器,否則會導(dǎo)致存儲的數(shù)據(jù)出問題,因此使用了ConcurrentHashMap
2、這里存在一個主線程和子線程的執(zhí)行順序問題,因為主線程需要等待線程池中所有線程下載圖片結(jié)束后才能往下走去壓縮圖片,如果主線程不等待子線程結(jié)束就向下執(zhí)行壓縮方法就會導(dǎo)致壓縮圖片缺少或者沒有壓縮圖片。因此可以使用CountDownLatch實現(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())可以解決,具體可以閱讀其源碼看實現(xiàn)。
下面是FTP工具類的實現(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下面是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(Listsrcfile, 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 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 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 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 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 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 srcfile=new ArrayList (); 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); } } Java有哪些集合類
Java中的集合主要分為四類:1、List列表:有序的,可重復(fù)的;2、Queue隊列:有序,可重復(fù)的;3、Set集合:不可重復(fù);4、Map映射:無序,鍵唯一,值不唯一。
關(guān)于怎么在java中利用多線程下載圖片并壓縮就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學(xué)到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。
分享文章:怎么在java中利用多線程下載圖片并壓縮
文章分享:http://weahome.cn/article/jhiipp.html