Recently, I am making a requirement: download the file storing the image url from the ftp directory of other systems, then read the URL address in the file, download the image according to the address and compress it into a package in a day. On average, one address file contains about 4,000 addresses. That is to say, after scanning a file, you need to download about 4,000 pictures, and then compress it. The following records my implementation method and optimization process. If you have any better ways, you can share it.
Framework used: SpringMVC
Timed task implementation: inherit org.springframework.scheduling.quartz.QuartzJobBean;
I won’t talk about the ftp environment construction. I have recorded it in other blogs that I use the FTP service built by CentOS in the virtual machine to create an FTP account and corresponding directory, and upload the image address file that needs to be downloaded in advance. File content format "Image ID||Image Address".
Method 1. The easiest way to implement it is to first download the file that stores the url address of the picture, then read the file traversal the picture address, adjust the downloaded picture method to store the picture locally, and finally compress the downloaded picture. After completion, delete the downloaded picture, and only retain the compressed package.
public class PictureTransferJob extends QuartzJobBean { protected void executeInternal(JobExecutionContext arg0) throws JobExecutionException { //The actual FTP configuration is obtained by reading the configuration file //FTP address String hostName ="192.168.1.112"; //FTP port int port = 2001; /FTP account String userName = "test1"; //ftp password String password = "test1"; //ftp file storage directory String ftpDowload = "/"; //The local storage path of the file String path = this.getClass().getResource("/").getPath(); //The image address file storage directory String addrPath=path.substring(1, path.indexOf("WEB-INF/classes"))+"picAddr"; //The actual downloaded image storage directory String picPath=path.substring(1, path.indexOf("WEB-INF/classes"))+"pic"; addrPath = addrPath.replace("%20"," "); picPath = picPath.replace("%20"," "); try { //Create the file creatFile(addrPath); //Create the file creatFile(picPath); String oldAddrPath = addrPath; String oldPicPath = picPath; //Create the FTP connection FtpUtil2 ftpUtil2 = new FtpUtil2(hostName, port,userName, password, ftpDowload, true); //Transf the file in the FTP directory String[] files = ftpUtil2.ListAllFiles(); //The local database will have a table record of the downloaded files. Here we will query the database and the file names listed in ftp. If the downloaded files will not be downloaded, and avoid repeated downloads. //The comparison process is omitted below, loop the files array, and create the file locally for(int i=0;i<files.length;i++){ creatFile(addrPath+File.separator+fileName); //ftpDowload is the address of the ftp server to store the file, addrPath is the address of the local storage file// Here is a return status to determine whether the file is downloaded successfully boolean downloadInvestorFlag = ftpUtil2.downloadFile(ftpDowload, addrPath); //A method to read the file after the file is downloaded successfully, and the image address to be downloaded is stored in the container boolean entityState = setPictureDetail(addrPath, picPath, fileNameDate); } } catch (Exception e) { e.printStackTrace(); //Click the business class that records the error log to send text messages that download file errors} } //Start reading the image address here private boolean setPictureDetail(String addrPath,String picPath,String synDate) { System.out.println("---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- String row; int count=0; //The image name and URL address read by each row are stored in the map. 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()); //The compression method is called here. The method that executes the downloaded image will be called in the compression method. ZipPic(picPath,syncDate,addrMap); System.out.println(new Date()); System.out.println("------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ e.printStackTrace(); } } } } /** * Download the picture according to the url address* @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(); //Create the Url object url=new URL(picAddr); is=url.openStream(); //The stream obtained by URLConnection will be written directly into the byte array through InputStream and will lose data, resulting in incomplete downloaded images. Use org.apache.commons.io.IOUtils.toByteArray(urlconnection.openstream()) to solve byte[] bytes=IOUtils.toByteArray(is); //new byte[is.available()]; get bytes // The data in the stream is read into the byte array, and after reading in, the data in the stream is cleared pic=new File(picPath+fileName+".jpg"); fos=new FileOutputStream(pic); fos.write(bytes); //Save the downloaded image into List, and after all the images are downloaded, pass in the zip method to compress 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(); } } } //This is the pseudo-code for compressed files private void zipPic(picPath,syncDate,addrMap);{ //Pause in the list of files that need to be compressed and the compressed file name ZipUtil.zipByStream(picList,new File(picPath+synDate+".zip")); } /** * Create file* @param path */ private void creatFile(String path) { File file = new File(path); if(!file.exists()) { file.mkdirs(); } } } } Method 2: Multi-threaded download, direct compression of streams
Method 1 Although the basic functions are implemented, because there are too many pictures that need to be downloaded, and compressing local image files and deleting pictures is also time-consuming, so there are two places where you can optimize the speed. One is to improve the efficiency of downloading pictures, and the other is to improve the efficiency of compression.
The method to improve download efficiency can use multi-threaded downloads, and the method to improve compression efficiency can directly compress the file stream without saving the image locally.
Multi-threading implementation method: First, we save the address list of files that need to be downloaded. If we want to use multi-threading to download, we must ensure that the pictures downloaded by different threads will not be repeated. Therefore, a flag is needed to distinguish them. At this time, we can use an index counter to divide them according to a certain amount of pictures downloaded by each thread. Starting from 0, every 400 images, we can use one thread to download every time, so that we can determine the number of threads needed, and the pictures downloaded by each thread will not be repeated.
Implementation method of compressed files: Because the essence of generating compressed files is to read the file stream that needs to be compressed, and then generate a compressed package, we can use the container to store the image stream data downloaded by all threads instead of creating the downloaded image file, and then pass the stream data to the compression tool class to directly compress it. This omits the tedious process of reading the image file to create the stream, then generating the compressed package, and then deleting the local image file.
The main implementations of the transformation are listed below:
/** * Compress the downloaded pictures by day* @throws IOException */ private boolean zipPic(String picPath,String synDate,Map<String, String> addrMap) throws IOException{ // Since it is a multi-threaded storage image stream, a thread-safe map is needed, so use ConcurrentHashMap Map<String,InputStream> pictureList=new ConcurrentHashMap<String,InputStream>(); //The number of pictures downloaded by each thread is defined here int count=400; //Storage the image address that needs to be downloaded List<Entry<String, String>> addrList=new ArrayList<Entry<String, String>>(addrMap.entrySet()); //The number of threads, add one because you want to create a thread to download the last less than 400 images int nThreads=(addrList.size()/count)+1; //CountDownLatch countDownLatch = new CountDownLatch(nThreads); try { boolean downPic=false; //Execute multithread download pictures downPic=downPic(picPath,addrList,picList,pictureList,nThreads,count); if (downPic) { ZipUtil.zipByArray(picList,new File(picPath+syncate+".zip")); } return true; } catch (Exception e) { e.printStackTrace(); return false; } }Here is the creation of a thread pool
/** * Download the picture according to the url address* @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); // Create two counters CountDownLatch begin=new CountDownLatch(0); CountDownLatch end=new CountDownLatch(nThreads); // Loop create thread for (int i = 0; i < nThreads; i++) { List<Entry<String, String>>subAddrList=null; // Calculate the data executed by each thread 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); } // Thread class PicDownload myhead = new PicDownload(picPath,subAddrList,picList,pictureList); // The way to execute threads here is to call the threadPool.execute(myhead) method in the thread pool. try { threadPool.execute(myhead); } catch (Exception e) { //Record error log return false; } } begin.countDown(); end.await(); // Close the thread pool threadPool.shutdown(); // Here you must loop until all threads in the thread pool have ended before going down. Due to this step during the test, the child thread downloaded the image but has not completed, and the main thread has gone down, resulting in no pictures in the compressed package // You can also use CountDownLatch to implement/*while (true) { if (threadPool.isTerminated()) { System.out.println("All child threads have ended!"); break; } }*/ return true; }The following is the thread implementation
class PicDownload implements Runnable{ //Download the address list of pictures List<Entry<String, String>> addrList; //Load the list of pictures successfully downloaded Map<String, byte[]> picList; Map<String, InputStream> pictureList; //The local storage path of the picture 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(); //Create the Url object url=new URL(picAddr); is=url.openStream(); //The stream obtained by URLConnection will be written directly into the byte array through InputStream and will lose data, resulting in incomplete downloaded images. Use org.apache.commons.io.IOUtils.toByteArray(urlconnection.openstream()) to solve //byte[] bytes=IOUtils.toByteArray(is); //new byte[is.available()]; the obtained bytes //The data in the stream is read into the byte array. After reading in, the data in the stream is cleared picList.put(fileName+".jpg", is); //At this time, since the stream is not written to the file, the stream must not be closed, otherwise the data in the stream will be lost //is.close(); } return true; } catch (Exception e) { e.printStackTrace(); return false; } finally{ //The stream cannot be closed/*if (null!=is) { is.close(); }*/ } } } I encountered another problem using streams for compression above. When compressing the file, java.net.SocketException:Connection reset
After analyzing the reason, it should be that the stream InputStream and UrlConnection are in the connection state, and the UrlConnection timeout reset causes the input stream to fail to get.
I tried to set the timeout time of URLConnection, but during the test, I found that the network speed of the image download received was greatly affected. This method is very unstable and undesirable. In the end, I only gave up using the stream and used a byte array to pass it to the compression tool class, and then converted the byte array to stream compression.
/** *Use container to store downloaded image byte array*/ 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(); //Create the Url object url=new URL(picAddr); //Open the connection and create the java.net.URLConnection object. This object has no method to close the connection. It can be converted to its subclass HttpURLConnection to call the disconnect method to close the connection. //java.net.URLConnection and java.net.HttpURLConnection both set timeout methods to close the connection //HttpURLConnection uc=(HttpURLConnection)url.openConnection(); is=uc.getInputStream(); //The stream obtained by URLConnection will be written directly into the byte array through InputStream and will lose data, resulting in incomplete downloaded images. Use org.apache.commons.io.IOUtils.toByteArray(urlconnection.openstream()) to solve byte[] bytes=IOUtils.toByteArray(is);//new byte[is.available()]; The obtained bytes // data in the stream is read into the byte array. After reading in, the data in the stream is cleared //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(); } } } Summarize:
Problems encountered during implementation:
1. When using thread pool, for the shared state, for example, the image byte data container stored here is shared by all threads, so a synchronized container is required, otherwise it will cause problems with the stored data. Therefore, ConcurrentHashMap<String,byte[]> is used.
2. There is a problem with the execution order of the main thread and the child thread here, because the main thread needs to wait for all threads in the thread pool to finish downloading images before going down to compress images. If the main thread does not wait for the child thread to end and executes the compression method downward, it will lead to missing or no compressed images. Therefore, you can use CountDownLatch to implement it, or use a dead loop to check threadPool.isTerminated() under the closing thread pool statement to continue executing the main thread to compress the image.
3. Since the input stream obtained by UrlConnection is directly transmitted to the compressed class for compression, there is a situation where the connection timeout resets, so instead, the downloaded stream is stored in a byte array and then passed to the compressed class to compress to avoid unexpected situations when using the stream.
4. After using urlconnection.openStream() to obtain the input stream, the image you converted to a byte array to download is incomplete. . It can be solved by using org.apache.commons.io.IOUtils.toByteArray(urlconnection.openstream()). For details, you can read the source code to view the implementation.
The following is the implementation of the FTP tool class:
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 server address private String hostName; // ftp server default port public static int defaultport = 21; // Login name private String userName; // Login password private String password; // Remote directory to access private String remoteDir; /** * @param hostName * Host address* @param port * Port number* @param userName * Username* @param password * Password * @param remoteDir * Default working directory * @param is_zhTimeZone * Whether it is Chinese FTP Server side* @return * @return */ /** * New method*/ 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"); } // Login(); // Switch the directory 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"); } // Log in to this.login(); // Switch the directory this.changeDir(this.remoteDir); this.setFileType(FTPClient.ASCII_FILE_TYPE); ftpClient.setDefaultPort(port); } /** * Log in to the FTP server*/ 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("Connect to ftp server: " + this.hostName + "Success..Start login"); return success; } private static FTPClientConfig Config() { FTPClientConfig conf = new FTPClientConfig(FTPClientConfig.SYST_UNIX); conf.setRecentDateFormatStr("MM month dd date HH:mm"); // conf.setRecentDateFormatStr("(YYYYY year)?MM month dd date(HH:mm)?"); return conf; } /** * Change working directory* * @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("Change the working directory to:" + remoteDir); } /** * Return to the previous level directory (parent directory) */ public void toParentDir() { try { ftpClient.changeToParentDirectory(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** * List all files in the current working directory */ public String[] ListAllFiles() { String[] names = this.ListFiles("*"); return this.sort(names); } /** * List matching files in the specified working directory * * @param dir * exp: /cim/ * @param file_regEx * The wildcard is * */ public String[] ListAllFiles(String dir, String file_regEx) { String[] names = this.ListFiles(dir + file_regEx); return this.sort(names); } /** * List matching files* * @param file_regEx * Match characters, wildcard characters are * */ 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(); } } /** * Set the type of the transferred file [text file or binary file] * * @param fileType * --BINARY_FILE_TYPE,ASCII_FILE_TYPE */ public void setFileType(int fileType) { try { ftpClient.setFileType(fileType); } catch (IOException e) { e.printStackTrace(); } } /** * Upload file* * @param localFilePath * --local file path + file name* @param newFileName * --new file name*/ public void uploadFile(String localFilePath, String newFileName) { // Upload file this.ftpClient.enterLocalPassiveMode();// Passive mode connection BufferedInputStream buffIn = null; try { buffIn = new BufferedInputStream(new FileInputStream(localFilePath)); boolean ifUpload = ftpClient.storeFile(newFileName, buffIn); if (!ifUpload) { System.out.println("Upload the file failed..."); } else { System.out.println("Upload the file successfully..."); } } catch (Exception e) { e.printStackTrace(); } finally { try { if (buffIn != null) buffIn.close(); } catch (Exception e) { e.printStackTrace(); } } } /** * Upload file 2 * * @param file * --FileInputStream file* @param newFileName * --New file name*/ public void newUploadFile(FileInputStream file, String newFileName) { // Upload the file this.ftpClient.enterLocalPassiveMode();// Passive mode connection BufferedInputStream buffIn = null; try { buffIn = new BufferedInputStream(file); boolean ifUpload = ftpClient.storeFile(newFileName, buffIn); if (!ifUpload) { System.out.println("Upload file failed..."); } else { System.out.println("Upload file successfully..."); } } catch (Exception e) { e.printStackTrace(); } finally { try { if (buffIn != null) buffIn.close(); } catch (Exception e) { e.printStackTrace(); } } } /** * Download file (single) * * @param remoteFileName * --File name on the server* @param localFileName * --local file name*/ public boolean downloadFile(String remoteFileName, String localFileName) { this.ftpClient.enterLocalPassiveMode();// Passive mode connection BufferedOutputStream buffOut = null; try { buffOut = new BufferedOutputStream(new FileOutputStream(localFileName)); boolean ifDownload = ftpClient .retrieveFile(remoteFileName, buffOut); if (!ifDownload) { System.out.println("Download file failed..."); return false; } else { System.out.println("Download file successfully..."); } } catch (Exception e) { e.printStackTrace(); return false; } finally { try { if (buffOut != null) buffOut.close(); } catch (Exception e) { e.printStackTrace(); } } return true; } /** * Close the FTP connection*/ public void close() { try { if (ftpClient != null) { ftpClient.logout(); ftpClient.disconnect(); } } catch (Exception e) { e.printStackTrace(); } } /** * Bubble sort string (from large to small) */ 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"); } }The following is the ZIP tool class:
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); /** * Compressed file* * @param srcfile File[] List of files that need to be compressed* @param zipfile File Compressed files*/ 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+"========================================================================================================================================================================================================================================================================================================================================================================================================================================== e) { log.error("ZipUtil zipFiles exception:"+e); } return outputStream; } /** * Compressed file* * @param srcfile File[] List of files that need to be compressed* @param zipfile File Compressed 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); } } /** * Compressed file* srcfile:key:file name, value: input stream corresponding to the file* @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()); } } /** * Compressed file* srcfile:key:file name, value: byte array corresponding to the file* @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()); } } /** * Unzip* * @param zipfile File File File that needs to be unzipped* @param descDir String Decompressed target directory*/ 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); } } The above is all the content of this article. I hope it will be helpful to everyone's learning and I hope everyone will support Wulin.com more.