Apache Commons常用工具類


 

Commons類庫

工具類就是為了提高開發效率而出現的,很多實現邏輯方式是固定的,那么就可以作為工具類使用,不需要重復實現,簡化代碼。

StringUtils

StringUtils是我們開發過程中常用的工具類,其中的的方法也比較熟悉,比如

兩個字符串的比較

//比較兩個字符串是否相同,即使a或者b有為空的情況,那么也能比較不會出現空指針現象 String a = "A"; String b = "B"; if (StringUtils.equals(a,b)){ System.out.println("a和b相同"); }else { System.out.println("a和b不相同"); } //超類Object有相同功能的方法equals,但是如a為空,那么就會出現空指針現象 String b = "B"; if (a.equals(b)){ System.out.println("a和b相同"); }else { System.out.println("a和b不相同"); } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

判斷字符串是否為空

//判斷字符串是否為空StringUtils工具類中有多個方法,可以根據注釋了解每種方法的具體使用方式 StringUtils.isAllBlank(a); StringUtils.isBlank(a); StringUtils.isAnyBlank(a); StringUtils.isAllEmpty(a); StringUtils.isEmpty(a); StringUtils.isAnyEmpty(a); //其中isBlank和isEmpty的區別在於如果字符串為空格字符串如:" ",那么isBlank會認為空返回true,而isEmpty不認為是空,返回false,其他方法類似 //當然StringuUtils也有對應判斷字符串不為空的方法,即在以上方法中名中加一個Not,如:isNotBlank 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

判斷包含關系

//判斷某個字符串是否包含另外一個字符串,StringUtils中提供了過個方法,其實通過方法名就能猜到每個方法的使用方式 StringUtils.contains(a,b); StringUtils.containsAny(a,b); StringUtils.containsNone(a,b); StringUtils.containsOnly(a,b); 
  • 1
  • 2
  • 3
  • 4
  • 5

其實StringUtils中很多方法與String中的方法相同,但是可以避免空指針異常,比如:

String中有方法startWith() 和 endWith() 若一個字符串為空的時候調用方法就會報空指針異常,但是使用StringUtils就可以避免

//若a為字符串,但是可能為空,那么就可能出現空指針 boolean rs = a.endWith("b"); //若使用工具類StringUtils,那么即使a為空也不會出現空指針 boolean rs = StringUtils.endWith(a,"b"); 
  • 1
  • 2
  • 3
  • 4
  • 5

StringUtils工具類還有其他的一些String用到的方法

StringUtils.replace() 將字符串中某些內容替換

StringUtils.indexOf() 判斷某個字符在字符串中的第一次出現的下標位置

StringUtils.lastIndexOf() 判斷某個字符在字符串中最后一次出現的位置

。。。。


DateUtils

DateUtils工具類我們通過類名就能明白這個類是對時間操作的工具類。

日期增加

如果我們想在當前時間推后一天,若按照以前的方式我們可能需要判斷目前的日期是的“日”是哪一天,如果是“30日”還需要判斷,月份是哪個月,有沒有31日,如果是28日,或者29日,還需要判斷是不是2月份,年份是閏年還是平年,如果是31日,還得判斷是哪個月,如果是12月份,那么月份就不能直接加一,而是賦值為一,等等一系列判斷,非常繁瑣。那么使用DateUtils只需要一行代碼就能解決。

//今天是2019年8月31日 String day = “2019年8月31日”; SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy年MM月dd日"); Date today = dateFormat.parse(day); Date tomorrow= DateUtils.addDays(today, 1); String rs = dateFormat.format(tomorrow); System.out.println(rs) 結果:2019年09月01日 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

注意:如果今天的時間寫錯了,比如:2019年8月32日,那么系統會自動將今天的時間變成2019年9月1日,明天的時間則為2019年09月02日

除了添加一天的方法,也有添加一小時,一周的方法等

    DateUtils.addYears(); //添加年 DateUtils.addMonths(); //添加月 DateUtils.addWeeks(); //添加周 DateUtils.addDays(); //添加天 DateUtils.addHours(); //添加小時 DateUtils.addMinutes(); //添加分鍾 DateUtils.addSeconds() //添加秒 。。。。。 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

日期比較

日期比較也是我們常用到的時間處理方式,比較兩個日期是否是同一天,那么可能需要先比較年,再比較月,最后比較日,整個代碼比較繁瑣,使用DateUtils工具類也是只需要一行代碼就能解決。

//判斷兩個日期是否相同 boolean sameDay = DateUtils.isSameDay(date2, date1); 
  • 1
  • 2

其他

DateUtils工具類還提供了將日期Date轉換成日歷的方法

Calendar calendar = DateUtils.toCalendar(date);
  • 1

CollectionUtils

CollectionUtils工具類是對集合的一些操作。可能我們平常最多用到的方法是判斷集合是否為空

//CollectionUtils不僅可以判斷Collection的子集合,也能判斷Map是否為空 boolean empty = CollectionUtils.isEmpty(list); 
  • 1
  • 2

判斷兩個集合是否有相同的元素

//判斷兩個集合如果有相同的元素返回true,反之返回false boolean b = CollectionUtils.containsAny(list, list2); 
  • 1
  • 2

將數組轉換成list集合

//平常在代碼中將數組轉換成list可能常用的java.util包 Arrays.asList() List<String> list = Arrays.asList(arr); //CollectionUtils工具類也提供了將訴數組轉換成list,返回的list是沒有泛型的 List list = CollectionUtils.arrayToList(arr); 
  • 1
  • 2
  • 3
  • 4
  • 5

獲取集合list 或者 set 的最后一個元素

//我們如果想要獲取list的最后一個元素的話可以使用下標,因為list的有序的 String last = list.get(list.size() - 1); //但是如果要獲取set集合的最后一個元素就比較麻煩,set的無序的沒有下標,但是可以使用CollectionUtils工具類 String last = CollectionUtils.lastElement(set); 
  • 1
  • 2
  • 3
  • 4

FileUtils

FileUtils工具類從名稱也能看出來是對文件的一些操作。

拷貝文件或目錄

復制文件或者文件夾,使用常規的方法,就會先從某個文件目錄中讀取文件或者文件夾,然后再寫出到另外一個文件目錄中,但是如果使用工具FileUtils就可以跟方便的實現,如下:

//將文件夾original中的文件全部拷貝到文件夾objective File srcDir = new File("G:\\original"); File destDir = new File("G:\\objective"); try { FileUtils.copyDirectory(srcDir,destDir); } catch (IOException e) { e.printStackTrace(); } //拷貝文件 File srcFile = new File("G:\\original\\src\\test.txt"); File destFile = new File("G:\\objective\\desc\\copy.txt"); try { FileUtils.copyFile(srcFile,destFile); } catch (IOException e) { e.printStackTrace(); } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

上面的方法是將某個目錄下的文件拷貝到另外的目錄下,或者將某個文件拷貝到另外一個文件中,下面還有其他拷貝方法

//本方法是將目錄original,整體拷貝到目錄objective中,即在目錄objective下面有個子目錄original File srcDir = new File("G:\\original"); File destDir = new File("G:\\objective"); try { FileUtils.copyDirectoryToDirectory(srcDir,destDir); } catch (IOException e) { e.printStackTrace(); } //將text.txt文件拷貝到objective目錄下,文件名保持原來的 File srcFile = new File("G:\\original\\src\\test.txt"); File file = new File("G:\\objective"); try { FileUtils.copyFileToDirectory(); } catch (IOException e) { e.printStackTrace(); } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

刪除文件或目錄

FileUtils提供了刪除文件或目錄的方法,比如要清空某個文件目錄下的所有內容,如下:

//清空目錄objective下的所有內容,但是不刪除objective目錄 File file = new File("G:\\objective"); try { FileUtils.cleanDirectory(new File("G:\\objective")); } catch (IOException e) { e.printStackTrace(); } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

與cleanDirectory()方法不同的還有一個刪除目錄的方法

//刪除目錄objective以及子目錄子文件,即G盤下沒有了objective目錄 File file = new File("G:\\objective"); try { FileUtils.deleteDirectory(file); } catch (IOException e) { e.printStackTrace(); } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

讀寫文件

FileUtils工具類中提供了一些讀取文件的方法

//讀取文件返回讀取的內容字符串,另一個重載的方法可以設置編碼 String context = FileUtils.readFileToString(file); String context = FileUtils.readFileToString(file,encoding); //讀取文件返回字節數組 byte[] bytes = FileUtils.readFileToByteArray(file); //讀取文件返回流 FileInputStream fileInputStream = FileUtils.openInputStream(file); FileOutputStream fileOutputStream = FileUtils.openOutputStream(file); //既然有讀取文件內容的方法那么必然也有寫的方法 FileUtils.writeStringToFile(file,data); FileUtils.writeStringToFile(file,data,encoding); 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

IOUtils

IOUtils是對流的操作,我們常常操作文件的時候就使用io流,所以上面FileUtils提到的文件復制也可以使用IOUtils實現,只是IOUtils是對文件流進行操作。

//IOUtils有多個重載的copy()方法,返回復制的字節數,示例如下: File srcFile = new File("G:\\original\\src\\test - 副本.txt"); File destFile = new File("G:\\objective\\desc\\copy.txt"); try { FileInputStream fileInputStream = FileUtils.openInputStream(srcFile); FileOutputStream fileOutputStream = FileUtils.openOutputStream(destFile); int copy = IOUtils.copy(fileInputStream, fileOutputStream); System.out.println(copy); } catch (IOException e) { e.printStackTrace(); } //copy方法 copy(InputStream input, OutputStream output) copy(InputStream input, Writer output) copy(InputStream input, Writer output, String encoding) copy(Reader input, Writer output) copy(Reader input, OutputStream output) copy(Reader input, OutputStream output, String encoding) 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

IOUtils還提供了兩個重載的方法,用於判斷兩個流的內容是否相同,比如讀取兩個文件返回了流,那么想要判斷兩個文件的內容是否相同,那么可以使用IOUtils提供的方法

            FileInputStream fileInputStream1 = FileUtils.openInputStream(destFile); FileInputStream fileInputStream2 = FileUtils.openInputStream(destFile1); boolean b = IOUtils.contentEquals(fileInputStream1, fileInputStream); System.out.println(b); //重載的方法 contentEquals(Reader input1, Reader input2) 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

HttpClient

HttpClient是 Apache Jakarta Common 下的子項目,用來提供高效的、最新的、功能豐富的支持 HTTP 協議的客戶端編程工具包,並且它支持 HTTP 協議最新的版本和建議。實現了所有 HTTP 的方法(GET,POST,PUT,HEAD 等)。以下是一個簡單的Http請求使用GET方法

    //客戶端 public static void main(String[] args) { //創建httpClient實例 HttpClient httpClient = new HttpClient(); //創建一個GET方法 GetMethod getMethod = new GetMethod("http://ip:port/MySpringBootDemo/api/test"); try { //發起get請求 int code = httpClient.executeMethod(getMethod); if (code != HttpStatus.SC_OK){ System.out.println("請求異常"); } byte[] responseBody = getMethod.getResponseBody(); System.out.println(new String(responseBody,"utf-8")); } catch (IOException e) { e.printStackTrace(); }finally { //釋放連接 getMethod.releaseConnection(); } } ............................................................................................................ //服務端 @RestController @RequestMapping("/api") public class ConfigurationApplication { @RequestMapping("test") @ResponseBody public void getNpws(HttpServletResponse response){ File file = new File("G:\\objective\\desc\\copy.txt"); getFile(response,file); } private void getFile(HttpServletResponse response,File file) { try( OutputStream output = response.getOutputStream(); FileInputStream input = new FileInputStream(file) ) { byte[] bts = new byte[1024]; int len = -1; while((len=input.read(bts))!=-1){ output.write(bts,0,len); } }catch (Exception e){ e.printStackTrace(); } } } 
  • 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

HttpClient可以設置一些參數,使用HttpClientParams

//HttpClient設置參數 httpClient.setParams(httpClientParams); HttpClientParams httpClientParams = new HttpClientParams(); //設置連接超時時間,單位是毫秒 httpClientParams.setConnectionManagerTimeout(long timeout); //設置是否先嘗試身份驗證 setAuthenticationPreemptive(boolean value) //設置字符集 setContentCharset(String charset) 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

GetMethod

上面的示例中用到了GetMethod,從名稱上能猜到這個類是發起GET請求的,那么它可能會提供一些get請求的配置

//設置請求頭,這個方法會覆蓋原來的請求頭 setRequestHeader(Header header) //添加請求頭,這個方法只是添加不會重寫原來的請求頭 addRequestHeader(Header header) //請求頭的創建可以使用無參構造函數,然后通過Header的兩個方法設置參數,請求頭是鍵值對key,value形式的,如: Hearder header = new Header(); header.setName("appToken"); header.setValue("adfdf"); //也可以通過有參構造函數直接創建 Header header = new Header("appToken","adfdf"); 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

請求類似IO流不能一直保持着,當請求完畢后要釋放連接

//當響應處理完畢后要斷開連接 releaseConnection(); 
  • 1
  • 2

PostMethod

http請求一般使用最多的就是get和post請求,下面我們看看PostMethod,其實和GetMethod類似

    public static void main(String[] args) { //創建HttpClient實例 HttpClient httpClient = new HttpClient(); String url = "http://192.168.0.115:8899/MySpringBootDemo/api/npws"; PostMethod postMethod = new PostMethod(url); //添加請求參數 postMethod.setParameter("ajbh","123"); Header header = new Header(); header.setName("token"); header.setValue("adfg"); //設置請求頭 postMethod.setRequestHeader(header); try { int code = httpClient.executeMethod(postMethod); if (code != HttpStatus.SC_OK){ System.out.println("請求異常"); } byte[] responseBody = postMethod.getResponseBody(); System.out.println(new String(responseBody)); } catch (IOException e) { e.printStackTrace(); }finally{ postMethod.releaseConnection(); } } } 
  • 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

一般我們使用post請求消息類型會選擇json格式的,PostMethod通過RequestEntity可以設置

//RequestEntity是一個接口,它有多個實現類分別是: //StringRequestEntity; ByteArrayRequestEntity; FileRequestEntity; InputStreamRequestEntity; MultipartRequestEntity JSONObject jsonObject = new JSONObject(); RequestEntity requestEntity = new StringRequestEntity(jsonObject.toString(),"application/json", "UTF-8"); postMethod.setRequestEntity(requestEntity); 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

HttpURLConnection

Apache commons 包中有一個工具類HttpURLConnection,它是java.net.HttpURLConnection的子類,Apache commons中的HttpURLConnection的方法都是不可用的,其實我們一般使用的都使用java.net.HttpURLConnection,所以下面的示例也是java.net.HttpURLConnection

//要請求的ip和端口 private static String ruleManagerServerUrl = "http://ip:端口"; public static void main(String[] args) { try { //獲取當前服務器地址 String localAddr = InetAddress.getLocalHost().getHostAddress(); JSONObject obj = new JSONObject(); obj.put("ip", localAddr); obj.put("port", "8080"); URL url = new URL(ruleManagerServerUrl + "/api/addHost"); HttpURLConnection connection = (HttpURLConnection)url.openConnection(); connection.setConnectTimeout(3000); connection.setRequestMethod("POST"); connection.setDoOutput(true); connection.setDoInput(true); connection.setRequestProperty("Content-Type", "application/json"); connection.setRequestProperty("Connection", "Keep-Alive"); connection.setRequestProperty("Charset", "UTF-8"); connection.setRequestProperty("accept", "application/json"); String s = obj.toJSONString(); byte[] writebytes = s.getBytes("UTF-8"); connection.setRequestProperty("Content-Length", String.valueOf(writebytes.length)); OutputStream out = connection.getOutputStream(); out.write(writebytes); out.flush(); out.close(); if (200 == connection.getResponseCode()) { String message = connection.getResponseMessage(); if (StringUtils.equals("添加服務器名稱失敗", message)) { logger.warn("添加服務器名稱失敗"); } } } catch (Exception var9) { logger.error("請求失敗", var9); } } 
  • 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

加密

Base64

平常開發中總會遇到加密的情況,比如登錄的用戶名和密碼會通過加密后存儲到數據庫中,其實就是將實際的用戶名和密碼通過另外一種算法進行編碼,隱藏了真正的內容,還有就是文本存儲到數據庫中的時候文本內容太大,那么就可以對文本內容進行編碼比如Base64后存儲到數據庫中。

public static void main(String[] args) { String str = "程序員"; Base64 base64 = new Base64(); String base64Str ; try { //Base64編碼 base64Str = base64.encodeToString(str.getBytes("UTF-8")); System.out.println(base64Str); }catch (Exception e){ logger.error("文本Base64編碼異常",e); return; } 結果:56iL5bqP5ZGY ............................................................................................................ //Base64解碼 byte[] decode = base64.decode(base64Str); try { String rs = new String(decode,"utf-8"); System.out.println(rs); }catch (Exception e){ logger.error("文本解碼異常",e); } } 結果:程序員 
  • 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

當然在java 中不止只有這一種Base64編碼方法,java.Util包中也有Base64

public static void main(String[] args) { String str = "程序員"; String base64Str; try { //Base64編碼 byte[] encode = Base64.getEncoder().encode(str.getBytes("utf-8")); base64Str = new String(encode,"utf-8"); System.out.println(base64Str); }catch (Exception e){ logger.error("Base64編碼異常",e); return; } //Base64解碼 byte[] decode = Base64.getDecoder().decode(base64Str); try { String rs = new String(decode,"utf-8"); System.out.println(rs); }catch (Exception e){ logger.error("Base64解碼異常",e); } } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

DigestUtils

DigestUtils是一個加密工具類,有各種加密的方法,但是我們常用到的是md5加密。當我們不知道這個工具類的時候想要對一段文字加密的時候會自己寫md5加密算法,如下:

package test; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; public class MD5Util { //第一種實現 public static void main(String[] args) { String string = "程序員"; char[] hexDigits={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; try { byte[] btInput = string.getBytes(); // 獲得MD5摘要算法的 MessageDigest 對象 MessageDigest mdInst = MessageDigest.getInstance("MD5"); // 使用指定的字節更新摘要 mdInst.update(btInput); // 獲得密文 byte[] md = mdInst.digest(); // 把密文轉換成十六進制的字符串形式 int j = md.length; char[] str = new char[j * 2]; int k = 0; for (int i = 0; i < j; i++) { byte byte0 = md[i]; str[k++] = hexDigits[byte0 >>> 4 & 0xf]; str[k++] = hexDigits[byte0 & 0xf]; } System.out.println(str); } catch (Exception e) { e.printStackTrace(); } } 結果:72D9ADF4944F23E5EFDE37F6364C126F ............................................................................................................ //第二種實現 public static void main(String[] args) { String string = "程序員"; try { MessageDigest md5 = MessageDigest.getInstance("MD5"); md5.update(string.getBytes()); byte[] b = md5.digest(); StringBuffer sb = new StringBuffer(); for (int n = 0; n < b.length; n++) { int i = b[n]; if (i < 0){ i += 256; } if (i < 16) { sb.append("0"); } sb.append(Integer.toHexString(i)); } System.out.println(sb.toString()); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } } 結果:72d9adf4944f23e5efde37f6364c126f 
  • 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

以上不論哪一種方法都需要大段的代碼,如果項目中多處使用,還需要封裝成一個工具類,其實Apache commons中已經有封裝好的工具類,使用很方便,一行代碼解決問題

        String s = DigestUtils.md5Hex(string); System.out.println(s); 結果:72d9adf4944f23e5efde37f6364c126f //當然工具類DigestUtils還提供了其他的md5加密方法 //加密字節數組 DigestUtils.md5Hex(byte[]); //加密流的 DigestUtils.md5Hex(inputStream); 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

文件壓縮zip

平常我們一般都是通過工具壓縮文件,比如360壓縮,好壓壓縮,那么現在我們學習一下使用java代碼壓縮文件,一下是zip普通方法壓縮文件夾

方法1:壓縮文件夾

public class ZipClass { private static final Logger logger = LoggerFactory.getLogger(ZipClass.class); private static final int BUFFER_SIZE = 2 * 1024; //主函數 public static void main(String[] args) { try { //壓縮文件名稱 File file = new File("G:\\original.zip"); //創建文件輸出流 FileOutputStream fileOutputStream = FileUtils.openOutputStream(file); //壓縮文件 toZip("G:\\original",fileOutputStream,true); } catch (IOException e) { logger.error("壓縮文件異常",e); } } /** * 壓縮成ZIP * @param srcDir 壓縮文件夾路徑 * @param out 壓縮文件輸出流 * @param keepDirStructure 是否保留原來的目錄結構(true:保留目錄結構;false:所有文件跑到壓縮包根目錄下) * (注意:不保留目錄結構可能會出現同名文件,會壓縮失敗) * @throws RuntimeException 壓縮失敗會拋出運行時異常 */ private static void toZip(String srcDir, OutputStream out, boolean keepDirStructure) throws RuntimeException{ //記錄壓縮開始時間 long start = System.currentTimeMillis(); //創建zip輸出流 try (ZipOutputStream zos = new ZipOutputStream(out)){ File sourceFile = new File(srcDir); compress(sourceFile,zos,sourceFile.getName(),keepDirStructure); //記錄壓縮結束時間 long end = System.currentTimeMillis(); System.out.println("壓縮完成,耗時:" + (end - start) +" ms"); } catch (Exception e) { logger.error("壓縮文件{}異常",srcDir,e); } } /** * 遞歸壓縮方法 * @param sourceFile 源文件 * @param zos zip輸出流 * @param name 壓縮后的名稱 * @param keepDirStructure 是否保留原來的目錄結構(true:保留目錄結構;false:所有文件跑到壓縮包根目錄下) * (注意:不保留目錄結構可能會出現同名文件,會壓縮失敗) * @throws Exception 異常 */ private static void compress(File sourceFile, ZipOutputStream zos, String name, boolean keepDirStructure) throws Exception{ byte[] buf = new byte[BUFFER_SIZE]; if(sourceFile.isFile()){ // 向zip輸出流中添加一個zip實體,構造器中name為zip實體的文件的名字 zos.putNextEntry(new ZipEntry(name)); // copy文件到zip輸出流中 int len; FileInputStream in = new FileInputStream(sourceFile); while ((len = in.read(buf)) != -1){ zos.write(buf, 0, len); } zos.closeEntry(); in.close(); } else { File[] listFiles = sourceFile.listFiles(); if(listFiles == null || listFiles.length == 0){ // 需要保留原來的文件結構時,需要對空文件夾進行處理 if(keepDirStructure){ // 空文件夾的處理 zos.putNextEntry(new ZipEntry(name + "/")); // 沒有文件,不需要文件的copy zos.closeEntry(); } }else { for (File file : listFiles) { // 判斷是否需要保留原來的文件結構 if (keepDirStructure) { // 注意:file.getName()前面需要帶上父文件夾的名字加一斜杠, // 不然最后壓縮包中就不能保留原來的文件結構,即:所有文件都跑到壓縮包根目錄下了 compress(file, zos, name + "/" + file.getName(),keepDirStructure); } else { compress(file, zos, file.getName(),keepDirStructure); } } } } } } 
  • 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

方法2:壓縮多個文件


    /** * 壓縮成ZIP 壓縮多個文件 * @param srcFiles 需要壓縮的文件列表 * @param out 壓縮文件輸出流 * @throws RuntimeException 壓縮失敗會拋出運行時異常 */ private static void toZip(List<File> srcFiles , OutputStream out)throws RuntimeException { long start = System.currentTimeMillis(); try (ZipOutputStream zos = new ZipOutputStream(out)){ for (File srcFile : srcFiles) { byte[] buf = new byte[BUFFER_SIZE]; zos.putNextEntry(new ZipEntry(srcFile.getName())); int len; FileInputStream in = new FileInputStream(srcFile); while ((len = in.read(buf)) != -1){ zos.write(buf, 0, len); } zos.closeEntry(); in.close(); } long end = System.currentTimeMillis(); System.out.println("壓縮完成,耗時:" + (end - start) +" ms"); } catch (Exception e) { throw new RuntimeException("zip error from ZipUtils",e); } } 
  • 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

Apache commons也提供了壓縮zip文件的方法:

 private static void toZip() { ZipArchiveEntry zipArchiveEntry = new ZipArchiveEntry("壓縮zip"); File file = new File("G:\\test1.txt"); try (FileInputStream inputStream = new FileInputStream(file)) { File zipFile = new File("G:\\test1.zip"); ZipArchiveOutputStream zipArchiveOutputStream = new ZipArchiveOutputStream(zipFile); zipArchiveOutputStream.putArchiveEntry(zipArchiveEntry); byte[] bytes = new byte[1024]; int len; while ((len = inputStream.read(bytes)) != -1){ zipArchiveOutputStream.write(len); } zipArchiveOutputStream.closeArchiveEntry(); zipArchiveOutputStream.close(); }catch (Exception e){ e.printStackTrace(); } } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

既然有壓縮文件,那么必然需要解壓

    /** * 解壓Zip文件 * * @param zipFile * 需要解壓的zip文件位置 * @param destDir * 解壓的目標位置 */ public static void unzip(String zipFile, String destDir) { File f; try (ArchiveInputStream i = new ArchiveStreamFactory().createArchiveInputStream(ArchiveStreamFactory.ZIP, Files.newInputStream(Paths.get(zipFile)))) { ArchiveEntry entry ; while ((entry = i.getNextEntry()) != null) { if (!i.canReadEntryData(entry)) { continue; } f = new File(destDir, entry.getName()); if (entry.isDirectory()) { if (!f.isDirectory() && !f.mkdirs()) { throw new IOException("failed to create directory " + f); } } else { File parent = f.getParentFile(); if (!parent.isDirectory() && !parent.mkdirs()) { throw new IOException("failed to create directory " + parent); } try (OutputStream o = Files.newOutputStream(f.toPath())) { IOUtils.copy(i, o); } } } } catch (IOException | ArchiveException e) { e.printStackTrace(); } 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM