一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - java多線程實現下載圖片并壓縮

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

2021-04-29 11:11Terisadeng Java教程

這篇文章主要為大家詳細介紹了java多線程實現下載圖片并壓縮,具有一定的參考價值,感興趣的小伙伴們可以參考一下

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

使用框架:springmvc

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

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

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
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個圖片就用一個線程下載,這樣就可以確定需要的線程個數,并且每個線程下載的圖片不會重復。

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

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/**
 * 將下載的圖片按天壓縮
 * @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;
 }
}

下面是創建線程池

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
/**
 * 根據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;
}

下面是線程實現

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
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的超時時間,但是測試時發現圖片下載收到網速影響較大,這種方式很不穩定,不可取,最后只有放棄使用流,而改用字節數組傳給壓縮工具類,然后將字節數組轉為流壓縮。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
/**
*使用容器存儲下載的圖片字節數組
*/
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工具類的實現:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
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工具類:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
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);
 }
}

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。

原文鏈接:https://blog.csdn.net/dongyuxu342719/article/details/80280726

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 超级碰在线视频 | 护士让我吃奶我扒她奶 | 操女人bb | 97精品国产自在现线免费 | 国产国语在线播放视频 | 完整秽淫刺激长篇小说 | 国产精品天天看天天爽 | 色女阁| 被夫上司侵犯了中文字幕 | 欧美日韩一区二区三区在线播放 | 国产亚洲综合精品一区二区三区 | 亚洲成人黄色 | 5278欧美一区二区三区 | 亚洲成人网导航 | jk制服蕾丝超短裙流白浆 | 风间由美被义子中文字幕 | 欧美一区二区三区不卡视频 | 无遮挡免费h肉动漫在线观看 | 和肥岳在厨房激情 | 视频在线视频免费观看 | 污到湿的爽文免费阅读 | 国产精品精品 | 男女做污事 | 双性双根 | 加勒比久草| 午夜爱爱片 | 1769最新资源站 | 日本邪恶动态 | 色噜噜亚洲男人的天堂www | 久久精品国产视频澳门 | 给我免费的视频在线观看 | se01在线看片 | 视频一区在线观看 | 四虎免费在线视频 | 久热这里只有精品99国产6 | 超h高h肉h文武侠 | 激情婷婷成人亚洲综合 | h肉动漫在线视频无修无遮挡 | 99久久无色码中文字幕 | 成人午夜爽爽爽免费视频 | 国产3p绿奴在线视频 |