Java-day28-其他流

1. 緩沖流

昨天學習了基本的一些流,作為IO流的入門,今天我們要見識一些更強大的流。比如能夠高效讀寫的緩沖流,能夠轉換編碼的轉換流,能夠持久化存儲對象的序列化流等等。這些功能更為強大的流,都是在基本的流對象基礎之上創建而來的,就像穿上鎧甲的武士一樣,相當于是對基本流對象的一種增強。

1.1 概述

緩沖流,也叫高效流,是對4個基本的FileXxx 流的增強,所以也是4個流,按照數據類型分類:

  • 字節緩沖流BufferedInputStreamBufferedOutputStream
  • 字符緩沖流BufferedReaderBufferedWriter

緩沖流的基本原理,是在創建流對象時,會創建一個內置的默認大小的緩沖區數組,通過緩沖區讀寫,減少系統IO次數,從而提高讀寫的效率。

1.2 字節緩沖流

構造方法

  • public BufferedInputStream(InputStream in) :創建一個 新的緩沖輸入流。
  • public BufferedOutputStream(OutputStream out): 創建一個新的緩沖輸出流。

構造舉例,代碼如下:

// 創建字節緩沖輸入流
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("bis.txt"));
// 創建字節緩沖輸出流
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("bos.txt"));

效率測試

查詢API,緩沖流讀寫方法與基本的流是一致的,我們通過復制大文件(375MB),測試它的效率。

  1. 基本流,代碼如下:
public class BufferedDemo {public static void main(String[] args) throws FileNotFoundException {// 記錄開始時間long start = System.currentTimeMillis();// 創建流對象try (FileInputStream fis = new FileInputStream("jdk9.exe");FileOutputStream fos = new FileOutputStream("copy.exe")){// 讀寫數據int b;while ((b = fis.read()) != -1) {fos.write(b);}} catch (IOException e) {e.printStackTrace();}// 記錄結束時間long end = System.currentTimeMillis();System.out.println("普通流復制時間:"+(end - start)+" 毫秒");}
}十幾分鐘過去了...
  1. 緩沖流,代碼如下:
public class BufferedDemo {public static void main(String[] args) throws FileNotFoundException {// 記錄開始時間long start = System.currentTimeMillis();// 創建流對象try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream("jdk9.exe"));BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("copy.exe"));){// 讀寫數據int b;while ((b = bis.read()) != -1) {bos.write(b);}} catch (IOException e) {e.printStackTrace();}// 記錄結束時間long end = System.currentTimeMillis();System.out.println("緩沖流復制時間:"+(end - start)+" 毫秒");}
}緩沖流復制時間:8016 毫秒

如何更快呢?

使用數組的方式,代碼如下:

public class BufferedDemo {public static void main(String[] args) throws FileNotFoundException {// 記錄開始時間long start = System.currentTimeMillis();// 創建流對象try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream("jdk9.exe"));BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("copy.exe"));){// 讀寫數據int len;byte[] bytes = new byte[8*1024];while ((len = bis.read(bytes)) != -1) {bos.write(bytes, 0 , len);}} catch (IOException e) {e.printStackTrace();}// 記錄結束時間long end = System.currentTimeMillis();System.out.println("緩沖流使用數組復制時間:"+(end - start)+" 毫秒");}
}
緩沖流使用數組復制時間:666 毫秒

1.3 字符緩沖流

構造方法

  • public BufferedReader(Reader in) :創建一個 新的緩沖輸入流。
  • public BufferedWriter(Writer out): 創建一個新的緩沖輸出流。

構造舉例,代碼如下:

// 創建字符緩沖輸入流
BufferedReader br = new BufferedReader(new FileReader("br.txt"));
// 創建字符緩沖輸出流
BufferedWriter bw = new BufferedWriter(new FileWriter("bw.txt"));

特有方法

字符緩沖流的基本方法與普通字符流調用方式一致,不再闡述,我們來看它們具備的特有方法。

  • BufferedReader:public String readLine(): 讀一行文字。
  • BufferedWriter:public void newLine(): 寫一行行分隔符,由系統屬性定義符號。

readLine方法演示,代碼如下:

public class BufferedReaderDemo {public static void main(String[] args) throws IOException {// 創建流對象BufferedReader br = new BufferedReader(new FileReader("in.txt"));// 定義字符串,保存讀取的一行文字String line  = null;// 循環讀取,讀取到最后返回nullwhile ((line = br.readLine())!=null) {System.out.print(line);System.out.println("------");}// 釋放資源br.close();}
}

newLine方法演示,代碼如下:

public class BufferedWriterDemo throws IOException {public static void main(String[] args) throws IOException  {// 創建流對象BufferedWriter bw = new BufferedWriter(new FileWriter("out.txt"));// 寫出數據bw.write("黑馬");// 寫出換行bw.newLine();bw.write("程序");bw.newLine();bw.write("員");bw.newLine();// 釋放資源bw.close();}
}
輸出效果:
黑馬
程序
員

1.4 練習:文本排序

請將文本信息恢復順序。

3.侍中、侍郎郭攸之、費祎、董允等,此皆良實,志慮忠純,是以先帝簡拔以遺陛下。愚以為宮中之事,事無大小,悉以咨之,然后施行,必得裨補闕漏,有所廣益。
8.愿陛下托臣以討賊興復之效,不效,則治臣之罪,以告先帝之靈。若無興德之言,則責攸之、祎、允等之慢,以彰其咎;陛下亦宜自謀,以咨諏善道,察納雅言,深追先帝遺詔,臣不勝受恩感激。
4.將軍向寵,性行淑均,曉暢軍事,試用之于昔日,先帝稱之曰能,是以眾議舉寵為督。愚以為營中之事,悉以咨之,必能使行陣和睦,優劣得所。
2.宮中府中,俱為一體,陟罰臧否,不宜異同。若有作奸犯科及為忠善者,宜付有司論其刑賞,以昭陛下平明之理,不宜偏私,使內外異法也。
1.先帝創業未半而中道崩殂,今天下三分,益州疲弊,此誠危急存亡之秋也。然侍衛之臣不懈于內,忠志之士忘身于外者,蓋追先帝之殊遇,欲報之于陛下也。誠宜開張圣聽,以光先帝遺德,恢弘志士之氣,不宜妄自菲薄,引喻失義,以塞忠諫之路也。
9.今當遠離,臨表涕零,不知所言。
6.臣本布衣,躬耕于南陽,茍全性命于亂世,不求聞達于諸侯。先帝不以臣卑鄙,猥自枉屈,三顧臣于草廬之中,咨臣以當世之事,由是感激,遂許先帝以驅馳。后值傾覆,受任于敗軍之際,奉命于危難之間,爾來二十有一年矣。
7.先帝知臣謹慎,故臨崩寄臣以大事也。受命以來,夙夜憂嘆,恐付托不效,以傷先帝之明,故五月渡瀘,深入不毛。今南方已定,兵甲已足,當獎率三軍,北定中原,庶竭駑鈍,攘除奸兇,興復漢室,還于舊都。此臣所以報先帝而忠陛下之職分也。至于斟酌損益,進盡忠言,則攸之、祎、允之任也。
5.親賢臣,遠小人,此先漢所以興隆也;親小人,遠賢臣,此后漢所以傾頹也。先帝在時,每與臣論此事,未嘗不嘆息痛恨于桓、靈也。侍中、尚書、長史、參軍,此悉貞良死節之臣,愿陛下親之信之,則漢室之隆,可計日而待也。

案例分析

  1. 逐行讀取文本信息。
  2. 把讀取到的文本存儲到集合中
  3. 對集合中的文本進行排序
  4. 遍歷集合,按順序,寫出文本信息。

案例實現

public class Demo05Test {public static void main(String[] args) throws IOException {//1.創建ArrayList集合,泛型使用StringArrayList<String> list = new ArrayList<>();//2.創建BufferedReader對象,構造方法中傳遞FileReader對象BufferedReader br = new BufferedReader(new FileReader("10_IO\\in.txt"));//3.創建BufferedWriter對象,構造方法中傳遞FileWriter對象BufferedWriter bw = new BufferedWriter(new FileWriter("10_IO\\out.txt"));//4.使用BufferedReader對象中的方法readLine,以行的方式讀取文本String line;while((line = br.readLine())!=null){//5.把讀取到的文本存儲到ArrayList集合中list.add(line);}//6.使用Collections集合工具類中的方法sort,對集合中的元素按照自定義規則排序Collections.sort(list, new Comparator<String>() {/*o1-o2:升序o2-o1:降序*/@Overridepublic int compare(String o1, String o2) {//依次比較集合中兩個元素的首字母,升序排序return o1.charAt(0)-o2.charAt(0);}});//7.遍歷ArrayList集合,獲取每一個元素for (String s : list) {//8.使用BufferedWriter對象中的方法wirte,把遍歷得到的元素寫入到文本中(內存緩沖區中)bw.write(s);//9.寫換行bw.newLine();}//10.釋放資源bw.close();br.close();}
}

2. 轉換流

2.1 字符編碼和字符集

字符編碼

計算機中儲存的信息都是用二進制數表示的,而我們在屏幕上看到的數字、英文、標點符號、漢字等字符是二進制數轉換之后的結果。按照某種規則,將字符存儲到計算機中,稱為編碼 。反之,將存儲在計算機中的二進制數按照某種規則解析顯示出來,稱為解碼 。比如說,按照A規則存儲,同樣按照A規則解析,那么就能顯示正確的文本符號。反之,按照A規則存儲,再按照B規則解析,就會導致亂碼現象。

編碼:字符(能看懂的)–字節(看不懂的)

解碼:字節(看不懂的)–>字符(能看懂的)

  • 字符編碼Character Encoding : 就是一套自然語言的字符與二進制數之間的對應規則。

    編碼表:生活中文字和計算機中二進制的對應規則

字符集

  • 字符集 Charset:也叫編碼表。是一個系統支持的所有字符的集合,包括各國家文字、標點符號、圖形符號、數字等。

計算機要準確的存儲和識別各種字符集符號,需要進行字符編碼,一套字符集必然至少有一套字符編碼。常見字符集有ASCII字符集、GBK字符集、Unicode字符集等。

可見,當指定了編碼,它所對應的字符集自然就指定了,所以編碼才是我們最終要關心的。

  • ASCII字符集
    • ASCII(American Standard Code for Information Interchange,美國信息交換標準代碼)是基于拉丁字母的一套電腦編碼系統,用于顯示現代英語,主要包括控制字符(回車鍵、退格、換行鍵等)和可顯示字符(英文大小寫字符、阿拉伯數字和西文符號)。
    • 基本的ASCII字符集,使用7位(bits)表示一個字符,共128字符。ASCII的擴展字符集使用8位(bits)表示一個字符,共256字符,方便支持歐洲常用字符。
  • ISO-8859-1字符集
    • 拉丁碼表,別名Latin-1,用于顯示歐洲使用的語言,包括荷蘭、丹麥、德語、意大利語、西班牙語等。
    • ISO-8859-1使用單字節編碼,兼容ASCII編碼。
  • GBxxx字符集
    • GB就是國標的意思,是為了顯示中文而設計的一套字符集。
    • GB2312:簡體中文碼表。一個小于127的字符的意義與原來相同。但兩個大于127的字符連在一起時,就表示一個漢字,這樣大約可以組合了包含7000多個簡體漢字,此外數學符號、羅馬希臘的字母、日文的假名們都編進去了,連在ASCII里本來就有的數字、標點、字母都統統重新編了兩個字節長的編碼,這就是常說的"全角"字符,而原來在127號以下的那些就叫"半角"字符了。
    • GBK:最常用的中文碼表。是在GB2312標準基礎上的擴展規范,使用了雙字節編碼方案,共收錄了21003個漢字,完全兼容GB2312標準,同時支持繁體漢字以及日韓漢字等。
    • GB18030:最新的中文碼表。收錄漢字70244個,采用多字節編碼,每個字可以由1個、2個或4個字節組成。支持中國國內少數民族的文字,同時支持繁體漢字以及日韓漢字等。
  • Unicode字符集
    • Unicode編碼系統為表達任意語言的任意字符而設計,是業界的一種標準,也稱為統一碼、標準萬國碼。
    • 它最多使用4個字節的數字來表達每個字母、符號,或者文字。有三種編碼方案,UTF-8、UTF-16和UTF-32。最為常用的UTF-8編碼。
    • UTF-8編碼,可以用來表示Unicode標準中任何字符,它是電子郵件、網頁及其他存儲或傳送文字的應用中,優先采用的編碼。互聯網工程工作小組(IETF)要求所有互聯網協議都必須支持UTF-8編碼。所以,我們開發Web應用,也要使用UTF-8編碼。它使用一至四個字節為每個字符編碼,編碼規則:
      1. 128個US-ASCII字符,只需一個字節編碼。
      2. 拉丁文等字符,需要二個字節編碼。
      3. 大部分常用字(含中文),使用三個字節編碼。
      4. 其他極少使用的Unicode輔助字符,使用四字節編碼。

2.2 編碼引出的問題

在IDEA中,使用FileReader 讀取項目中的文本文件。由于IDEA的設置,都是默認的UTF-8編碼,所以沒有任何問題。但是,當讀取Windows系統中創建的文本文件時,由于Windows系統的默認是GBK編碼,就會出現亂碼。

public class ReaderDemo {public static void main(String[] args) throws IOException {FileReader fileReader = new FileReader("E:\\File_GBK.txt");int read;while ((read = fileReader.read()) != -1) {System.out.print((char)read);}fileReader.close();}
}
輸出結果:
���

那么如何讀取GBK編碼的文件呢?

2.3 InputStreamReader類

轉換流java.io.InputStreamReader,是Reader的子類,是從字節流到字符流的橋梁。它讀取字節,并使用指定的字符集將其解碼為字符。它的字符集可以由名稱指定,也可以接受平臺的默認字符集。

構造方法

  • InputStreamReader(InputStream in): 創建一個使用默認字符集的字符流。
  • InputStreamReader(InputStream in, String charsetName): 創建一個指定字符集的字符流。

構造舉例,代碼如下:

InputStreamReader isr = new InputStreamReader(new FileInputStream("in.txt"));
InputStreamReader isr2 = new InputStreamReader(new FileInputStream("in.txt") , "GBK");

指定編碼讀取

public class ReaderDemo2 {public static void main(String[] args) throws IOException {// 定義文件路徑,文件為gbk編碼String FileName = "E:\\file_gbk.txt";// 創建流對象,默認UTF8編碼InputStreamReader isr = new InputStreamReader(new FileInputStream(FileName));// 創建流對象,指定GBK編碼InputStreamReader isr2 = new InputStreamReader(new FileInputStream(FileName) , "GBK");// 定義變量,保存字符int read;// 使用默認編碼字符流讀取,亂碼while ((read = isr.read()) != -1) {System.out.print((char)read); // ��?�}isr.close();// 使用指定編碼字符流讀取,正常解析while ((read = isr2.read()) != -1) {System.out.print((char)read);// 大家好}isr2.close();}
}

2.4 OutputStreamWriter類

轉換流java.io.OutputStreamWriter ,是Writer的子類,是從字符流到字節流的橋梁。使用指定的字符集將字符編碼為字節。它的字符集可以由名稱指定,也可以接受平臺的默認字符集。

構造方法

  • OutputStreamWriter(OutputStream in): 創建一個使用默認字符集的字符流。
  • OutputStreamWriter(OutputStream in, String charsetName): 創建一個指定字符集的字符流。

構造舉例,代碼如下:

OutputStreamWriter isr = new OutputStreamWriter(new FileOutputStream("out.txt"));
OutputStreamWriter isr2 = new OutputStreamWriter(new FileOutputStream("out.txt") , "GBK");

指定編碼寫出

public class OutputDemo {public static void main(String[] args) throws IOException {// 定義文件路徑String FileName = "E:\\out.txt";// 創建流對象,默認UTF8編碼OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(FileName));// 寫出數據osw.write("你好"); // 保存為6個字節osw.close();// 定義文件路徑String FileName2 = "E:\\out2.txt";// 創建流對象,指定GBK編碼OutputStreamWriter osw2 = new OutputStreamWriter(new FileOutputStream(FileName2),"GBK");// 寫出數據osw2.write("你好");// 保存為4個字節osw2.close();}
}

轉換流理解圖解

轉換流是字節與字符間的橋梁!

2.5 練習:轉換文件編碼

將GBK編碼的文本文件,轉換為UTF-8編碼的文本文件。

案例分析

  1. 指定GBK編碼的轉換流,讀取文本文件。
  2. 使用UTF-8編碼的轉換流,寫出文本文件。

案例實現

public class TransDemo {public static void main(String[] args) {      // 1.定義文件路徑String srcFile = "file_gbk.txt";String destFile = "file_utf8.txt";// 2.創建流對象// 2.1 轉換輸入流,指定GBK編碼InputStreamReader isr = new InputStreamReader(new FileInputStream(srcFile) , "GBK");// 2.2 轉換輸出流,默認utf8編碼OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(destFile));// 3.讀寫數據// 3.1 定義數組char[] cbuf = new char[1024];// 3.2 定義長度int len;// 3.3 循環讀取while ((len = isr.read(cbuf))!=-1) {// 循環寫出osw.write(cbuf,0,len);}// 4.釋放資源osw.close();isr.close();}
}

3. 序列化

3.1 概述

Java 提供了一種對象序列化的機制。用一個字節序列可以表示一個對象,該字節序列包含該對象的數據對象的類型對象中存儲的屬性等信息。字節序列寫出到文件之后,相當于文件中持久保存了一個對象的信息。

反之,該字節序列還可以從文件中讀取回來,重構對象,對它進行反序列化對象的數據對象的類型對象中存儲的數據信息,都可以用來在內存中創建對象。看圖理解序列化:

3.2 ObjectOutputStream類

java.io.ObjectOutputStream 類,將Java對象的原始數據類型寫出到文件,實現對象的持久存儲。

構造方法

  • public ObjectOutputStream(OutputStream out) : 創建一個指定OutputStream的ObjectOutputStream。

構造舉例,代碼如下:

FileOutputStream fileOut = new FileOutputStream("employee.txt");
ObjectOutputStream out = new ObjectOutputStream(fileOut);

序列化操作

  1. 一個對象要想序列化,必須滿足兩個條件:
  • 該類必須實現java.io.Serializable 接口,Serializable 是一個標記接口,不實現此接口的類將不會使任何狀態序列化或反序列化,會拋出NotSerializableException
  • 該類的所有屬性必須是可序列化的。如果有一個屬性不需要可序列化的,則該屬性必須注明是瞬態的,使用transient 關鍵字修飾。
public class Employee implements java.io.Serializable {public String name;public String address;public transient int age; // transient瞬態修飾成員,不會被序列化public void addressCheck() {System.out.println("Address  check : " + name + " -- " + address);}
}

2.寫出對象方法

  • public final void writeObject (Object obj) : 將指定的對象寫出。
public class SerializeDemo{public static void main(String [] args)   {Employee e = new Employee();e.name = "zhangsan";e.address = "beiqinglu";e.age = 20; try {// 創建序列化流對象ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("employee.txt"));// 寫出對象out.writeObject(e);// 釋放資源out.close();fileOut.close();System.out.println("Serialized data is saved"); // 姓名,地址被序列化,年齡沒有被序列化。} catch(IOException i)   {i.printStackTrace();}}
}
輸出結果:
Serialized data is saved

3.3 ObjectInputStream類

ObjectInputStream反序列化流,將之前使用ObjectOutputStream序列化的原始數據恢復為對象。

構造方法

  • public ObjectInputStream(InputStream in) : 創建一個指定InputStream的ObjectInputStream。

反序列化操作1

如果能找到一個對象的class文件,我們可以進行反序列化操作,調用ObjectInputStream讀取對象的方法:

  • public final Object readObject () : 讀取一個對象。
public class DeserializeDemo {public static void main(String [] args)   {Employee e = null;try {       // 創建反序列化流FileInputStream fileIn = new FileInputStream("employee.txt");ObjectInputStream in = new ObjectInputStream(fileIn);// 讀取一個對象e = (Employee) in.readObject();// 釋放資源in.close();fileIn.close();}catch(IOException i) {// 捕獲其他異常i.printStackTrace();return;}catch(ClassNotFoundException c)  {// 捕獲類找不到異常System.out.println("Employee class not found");c.printStackTrace();return;}// 無異常,直接打印輸出System.out.println("Name: " + e.name);  // zhangsanSystem.out.println("Address: " + e.address); // beiqingluSystem.out.println("age: " + e.age); // 0}
}

對于JVM可以反序列化對象,它必須是能夠找到class文件的類。如果找不到該類的class文件,則拋出一個 ClassNotFoundException 異常。

反序列化操作2

**另外,當JVM反序列化對象時,能找到class文件,但是class文件在序列化對象之后發生了修改,那么反序列化操作也會失敗,拋出一個InvalidClassException異常。**發生這個異常的原因如下:

  • 該類的序列版本號與從流中讀取的類描述符的版本號不匹配
  • 該類包含未知數據類型
  • 該類沒有可訪問的無參數構造方法

Serializable 接口給需要序列化的類,提供了一個序列版本號。serialVersionUID 該版本號的目的在于驗證序列化的對象和對應類是否版本匹配。

public class Employee implements java.io.Serializable {// 加入序列版本號private static final long serialVersionUID = 1L;public String name;public String address;// 添加新的屬性 ,重新編譯, 可以反序列化,該屬性賦為默認值.public int eid; public void addressCheck() {System.out.println("Address  check : " + name + " -- " + address);}
}

3.4 練習:序列化集合

  1. 將存有多個自定義對象的集合序列化操作,保存到list.txt文件中。
  2. 反序列化list.txt ,并遍歷集合,打印對象信息。

案例分析

  1. 把若干學生對象 ,保存到集合中。
  2. 把集合序列化。
  3. 反序列化讀取時,只需要讀取一次,轉換為集合類型。
  4. 遍歷集合,可以打印所有的學生信息

案例實現

public class SerTest {public static void main(String[] args) throws Exception {// 創建 學生對象Student student = new Student("老王", "laow");Student student2 = new Student("老張", "laoz");Student student3 = new Student("老李", "laol");ArrayList<Student> arrayList = new ArrayList<>();arrayList.add(student);arrayList.add(student2);arrayList.add(student3);// 序列化操作// serializ(arrayList);// 反序列化  ObjectInputStream ois  = new ObjectInputStream(new FileInputStream("list.txt"));// 讀取對象,強轉為ArrayList類型ArrayList<Student> list  = (ArrayList<Student>)ois.readObject();for (int i = 0; i < list.size(); i++ ){Student s = list.get(i);System.out.println(s.getName()+"--"+ s.getPwd());}}private static void serializ(ArrayList<Student> arrayList) throws Exception {// 創建 序列化流 ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("list.txt"));// 寫出對象oos.writeObject(arrayList);// 釋放資源oos.close();}
}

4. 打印流

4.1 概述

平時我們在控制臺打印輸出,是調用print方法和println方法完成的,這兩個方法都來自于java.io.PrintStream類,該類能夠方便地打印各種數據類型的值,是一種便捷的輸出方式。

4.2 PrintStream類

構造方法

  • public PrintStream(String fileName) : 使用指定的文件名創建一個新的打印流。

構造舉例,代碼如下:

PrintStream ps = new PrintStream("ps.txt")

改變打印流向

System.out就是PrintStream類型的,只不過它的流向是系統規定的,打印在控制臺上。不過,既然是流對象,我們就可以玩一個"小把戲",改變它的流向。

public class PrintDemo {public static void main(String[] args) throws IOException {// 調用系統的打印流,控制臺直接輸出97System.out.println(97);// 創建打印流,指定文件的名稱PrintStream ps = new PrintStream("ps.txt");// 設置系統的打印流流向,輸出到ps.txtSystem.setOut(ps);// 調用系統的打印流,ps.txt中輸出97System.out.println(97);}
}

5. 壓縮流和解壓縮流

壓縮流:

? 負責壓縮文件或者文件夾

解壓縮流:

? 負責把壓縮包中的文件和文件夾解壓出來

/*
*   解壓縮流
*
* */
public class ZipStreamDemo1 {public static void main(String[] args) throws IOException {//1.創建一個File表示要解壓的壓縮包File src = new File("D:\\aaa.zip");//2.創建一個File表示解壓的目的地File dest = new File("D:\\");//調用方法unzip(src,dest);}//定義一個方法用來解壓public static void unzip(File src,File dest) throws IOException {//解壓的本質:把壓縮包里面的每一個文件或者文件夾讀取出來,按照層級拷貝到目的地當中//創建一個解壓縮流用來讀取壓縮包中的數據ZipInputStream zip = new ZipInputStream(new FileInputStream(src));//要先獲取到壓縮包里面的每一個zipentry對象//表示當前在壓縮包中獲取到的文件或者文件夾ZipEntry entry;while((entry = zip.getNextEntry()) != null){System.out.println(entry);if(entry.isDirectory()){//文件夾:需要在目的地dest處創建一個同樣的文件夾File file = new File(dest,entry.toString());file.mkdirs();}else{//文件:需要讀取到壓縮包中的文件,并把他存放到目的地dest文件夾中(按照層級目錄進行存放)FileOutputStream fos = new FileOutputStream(new File(dest,entry.toString()));int b;while((b = zip.read()) != -1){//寫到目的地fos.write(b);}fos.close();//表示在壓縮包中的一個文件處理完畢了。zip.closeEntry();}}zip.close();}
}
public class ZipStreamDemo2 {public static void main(String[] args) throws IOException {/**   壓縮流*      需求:*          把D:\\a.txt打包成一個壓縮包* *///1.創建File對象表示要壓縮的文件File src = new File("D:\\a.txt");//2.創建File對象表示壓縮包的位置File dest = new File("D:\\");//3.調用方法用來壓縮toZip(src,dest);}/**   作用:壓縮*   參數一:表示要壓縮的文件*   參數二:表示壓縮包的位置* */public static void toZip(File src,File dest) throws IOException {//1.創建壓縮流關聯壓縮包ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(new File(dest,"a.zip")));//2.創建ZipEntry對象,表示壓縮包里面的每一個文件和文件夾//參數:壓縮包里面的路徑ZipEntry entry = new ZipEntry("aaa\\bbb\\a.txt");//3.把ZipEntry對象放到壓縮包當中zos.putNextEntry(entry);//4.把src文件中的數據寫到壓縮包當中FileInputStream fis = new FileInputStream(src);int b;while((b = fis.read()) != -1){zos.write(b);}zos.closeEntry();zos.close();}
}
public class ZipStreamDemo3 {public static void main(String[] args) throws IOException {/**   壓縮流*      需求:*          把D:\\aaa文件夾壓縮成一個壓縮包* *///1.創建File對象表示要壓縮的文件夾File src = new File("D:\\aaa");//2.創建File對象表示壓縮包放在哪里(壓縮包的父級路徑)File destParent = src.getParentFile();//D:\\//3.創建File對象表示壓縮包的路徑File dest = new File(destParent,src.getName() + ".zip");//4.創建壓縮流關聯壓縮包ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(dest));//5.獲取src里面的每一個文件,變成ZipEntry對象,放入到壓縮包當中toZip(src,zos,src.getName());//aaa//6.釋放資源zos.close();}/**   作用:獲取src里面的每一個文件,變成ZipEntry對象,放入到壓縮包當中*   參數一:數據源*   參數二:壓縮流*   參數三:壓縮包內部的路徑* */public static void toZip(File src,ZipOutputStream zos,String name) throws IOException {//1.進入src文件夾File[] files = src.listFiles();//2.遍歷數組for (File file : files) {if(file.isFile()){//3.判斷-文件,變成ZipEntry對象,放入到壓縮包當中ZipEntry entry = new ZipEntry(name + "\\" + file.getName());//aaa\\no1\\a.txtzos.putNextEntry(entry);//讀取文件中的數據,寫到壓縮包FileInputStream fis = new FileInputStream(file);int b;while((b = fis.read()) != -1){zos.write(b);}fis.close();zos.closeEntry();}else{//4.判斷-文件夾,遞歸toZip(file,zos,name + "\\" + file.getName());//     no1            aaa   \\   no1}}}
}

6. 工具包(Commons-io)

介紹:

? Commons是apache開源基金組織提供的工具包,里面有很多幫助我們提高開發效率的API

比如:

? StringUtils 字符串工具類

? NumberUtils 數字工具類

? ArrayUtils 數組工具類

? RandomUtils 隨機數工具類

? DateUtils 日期工具類

? StopWatch 秒表工具類

? ClassUtils 反射工具類

? SystemUtils 系統工具類

? MapUtils 集合工具類

? Beanutils bean工具類

? Commons-io io的工具類

? 等等…

其中:Commons-io是apache開源基金組織提供的一組有關IO操作的開源工具包。

作用:提高IO流的開發效率。

使用方式:

1,新建lib文件夾

2,把第三方jar包粘貼到文件夾中

3,右鍵點擊add as a library

代碼示例:

public class CommonsIODemo1 {public static void main(String[] args) throws IOException {/*FileUtils類static void copyFile(File srcFile, File destFile)                   復制文件static void copyDirectory(File srcDir, File destDir)                復制文件夾static void copyDirectoryToDirectory(File srcDir, File destDir)     復制文件夾static void deleteDirectory(File directory)                         刪除文件夾static void cleanDirectory(File directory)                          清空文件夾static String readFileToString(File file, Charset encoding)         讀取文件中的數據變成成字符串static void write(File file, CharSequence data, String encoding)    寫出數據IOUtils類public static int copy(InputStream input, OutputStream output)      復制文件public static int copyLarge(Reader input, Writer output)            復制大文件public static String readLines(Reader input)                        讀取數據public static void write(String data, OutputStream output)          寫出數據*//* File src = new File("myio\\a.txt");File dest = new File("myio\\copy.txt");FileUtils.copyFile(src,dest);*//*File src = new File("D:\\aaa");File dest = new File("D:\\bbb");FileUtils.copyDirectoryToDirectory(src,dest);*//*File src = new File("D:\\bbb");FileUtils.cleanDirectory(src);*/}
}

7. 工具包(hutool)

介紹:

? Commons是國人開發的開源工具包,里面有很多幫助我們提高開發效率的API

比如:

? DateUtil 日期時間工具類

? TimeInterval 計時器工具類

? StrUtil 字符串工具類

? HexUtil 16進制工具類

? HashUtil Hash算法類

? ObjectUtil 對象工具類

? ReflectUtil 反射工具類

? TypeUtil 泛型類型工具類

? PageUtil 分頁工具類

? NumberUtil 數字工具類

使用方式:

1,新建lib文件夾

2,把第三方jar包粘貼到文件夾中

3,右鍵點擊add as a library

代碼示例:

public class Test1 {public static void main(String[] args) {/*FileUtil類:file:根據參數創建一個file對象touch:根據參數創建文件writeLines:把集合中的數據寫出到文件中,覆蓋模式。appendLines:把集合中的數據寫出到文件中,續寫模式。readLines:指定字符編碼,把文件中的數據,讀到集合中。readUtf8Lines:按照UTF-8的形式,把文件中的數據,讀到集合中copy:拷貝文件或者文件夾*//* File file1 = FileUtil.file("D:\\", "aaa", "bbb", "a.txt");System.out.println(file1);//D:\aaa\bbb\a.txtFile touch = FileUtil.touch(file1);System.out.println(touch);ArrayList<String> list = new ArrayList<>();list.add("aaa");list.add("aaa");list.add("aaa");File file2 = FileUtil.writeLines(list, "D:\\a.txt", "UTF-8");System.out.println(file2);*//*  ArrayList<String> list = new ArrayList<>();list.add("aaa");list.add("aaa");list.add("aaa");File file3 = FileUtil.appendLines(list, "D:\\a.txt", "UTF-8");System.out.println(file3);*/List<String> list = FileUtil.readLines("D:\\a.txt", "UTF-8");System.out.println(list);}
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/86907.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/86907.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/86907.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

S712001 開放式用戶通信

開放式用戶通信分類 TIA PORTAL 軟件內提供了以下指令&#xff1a; 不帶連接管理的通信指令 “TCON ” &#xff1a;建立以太網連接“TDISCON” &#xff1a;斷開以太網連接“TSEND” &#xff1a;TCP 和 ISO ON TCP 使用的發送數據“TRCV”&#xff1a; TCP 和 ISO ON TCP 使…

CSMatIO庫的安裝與C#實現.mat文件生成

一.CSMatIO介紹 CSMatIO 是一個用于讀寫 MATLAB .mat 文件的開源 C# 庫&#xff0c;它提供了簡單而高效的 API&#xff0c;使 .NET 應用程序能夠與 MATLAB 進行數據交換&#xff0c;支持讀取和寫入 MATLAB 的 .mat 文件&#xff08;版本 5 和 7.3&#xff09;&#xff0c;兼容…

設計一個interface (一)

好的&#xff0c;我來舉一個具體的例子&#xff0c;幫助你理解 interface、element、resource 和 architecture 之間的關系。 場景&#xff1a;設計一個用戶管理系統的接口 背景 假設我們正在設計一個用戶管理系統&#xff0c;系統中有兩個主要的模塊&#xff1a; 用戶服務模…

tomcat下載安裝

目錄 一.tomact簡介 二.詳細步驟 三.下載頁面詳解&#xff08;選看&#xff09; 一.tomact簡介 Tomcat是Apache軟件基金會下的一個核心項目&#xff0c;它是一個開源的Java Servlet和JSP容器。由Apache、Sun等公司及個人共同開發&#xff0c;由于Sun的參與&#xff0c;最新的…

Axure版AntDesign 元件庫-免費版

AntDesign 元件庫概述 一、AntDesign 元件庫概述 添加圖片注釋&#xff0c;不超過 140 字&#xff08;可選&#xff09; AntDesign 是螞蟻集團推出的企業級設計體系&#xff0c;在 Axure 中使用 AntDesign 元件庫&#xff0c;可幫助設計師快速搭建符合現代企業級產品標準的高…

MySQL鎖機制全解析

MYSQL存儲引擎支持的鎖 InnoDB支持行級鎖(row-level locking)和表級鎖,默認為行級鎖。MyISAM采用表級鎖(table-level locking) 鎖的基本分類 1. 按照鎖的使用方式 , Mysql的鎖大致分為共享鎖和排它鎖 a. 共享鎖(S) 共享鎖&#xff0c;Share lock&#xff0c;又稱為讀鎖&am…

圖解Git中Rebase與Merge的區別

文章目錄 前言理解基本概念&#x1f500; Git Merge&#xff1a;合并分支&#x1f504; Git Rebase&#xff1a;重寫歷史 可視化理解工作流程實際應用場景與示例場景1&#xff1a;團隊協作 - 使用Merge場景2&#xff1a;個人分支整理 - 使用Rebase沖突解決&#xff1a;兩種策略…

2 Qt中的空窗口外觀設置和常用的基礎部件

Widget空窗口 this->setWindowTitle("我的窗口");//設置窗口標題this->resize(500,300);//設置窗口大小this->setFixedSize(500,300);//設置固定大小&#xff08;無法拖拽&#xff09; 此時&#xff0c;窗口大小發生改變&#xff0c;且窗口名稱改變&#x…

常用 Python 編輯器

可以使用任何文本編輯器來編寫 Python 程序&#xff0c;只要遵循 Python 語法且保存為文件&#xff0c;程序都可以通過 python 命令運行。不過&#xff0c;使用功能豐富的專用編輯器會帶來更好的編程體驗。 當今最常用的幾個 Python 編輯器&#xff08;也稱 IDE 或代碼編輯器&a…

Java+Vue開發的電子采購管理系統,助力企業采購智能化,提升效率促發展

前言&#xff1a; 在當今數字化時代&#xff0c;企業采購管理面臨著提高效率、降低成本、增強透明度等諸多挑戰。傳統的采購模式往往存在流程繁瑣、信息傳遞不及時、管理難度大等問題。電子采購管理系統應運而生&#xff0c;它借助先進的互聯網技術和信息化手段&#xff0c;將…

嵌入式網絡通信與物聯網協議全解析:Wi-Fi、BLE、LoRa、ZigBee 實戰指南

來源&#xff1a;0voice/EmbeddedSoftwareLearn 一、為什么嵌入式一定要搞懂網絡通信&#xff1f; 在傳統的裸機或單機嵌入式項目里&#xff0c;我們習慣了“點燈、串口、IC/SPI、RTOS 多任務”這樣的套路。但當一個設備需要與云平臺、手機 App 或其他設備實時交互時&#xff…

【補充筆記●推薦方案】解決 Docker “open \.\pipe\docker_engine: Access is denied” 權限問題

starting services: initializing Docker API Proxy: setting up docker api proxy listener: open \\.\pipe\docker_engine: Access is denied.引言 【筆記】解決 WSL 遷移后 Docker 出現 “starting services: initializing Docker API Proxy: setting up docker ap” 問題-…

AI編程工具深度對比:騰訊云代碼助手CodeBuddy、Cursor與通義靈碼

騰訊云代碼助手 CodeBuddy 智能代碼補全&#xff1a;基于上下文和編輯行為預測代碼&#xff0c;支持行內補全、函數塊生成及注釋轉代碼&#xff0c;覆蓋200編程語言和框架&#xff0c;可減少70%以上的鍵盤輸入。Craft智能體&#xff1a;支持自然語言驅動的多文件協同開發&…

Redis 的集群

深入理解 Redis 的集群模式與高可用機制 Redis 是一款廣泛應用于高性能緩存與存儲系統的 NoSQL 數據庫。隨著業務的發展&#xff0c;如何提升 Redis 的高可用性和水平擴展能力成為架構設計的關鍵。本篇博客將系統講解 Redis 的不同集群模式及其高可用策略&#xff0c;深入剖析其…

基于Dify平臺構建AI應用

2022年底openAI的chatgpt的出現&#xff0c;讓人們看到生成式AI的能力如此強大&#xff0c;引燃了生成式AI的一波浪潮。2025年春節前&#xff0c;DeepSeek的橫空出世讓大模型這個領域變得人人都可以參與進來&#xff0c;生成式AI大模型不再有非常高的顯卡的門檻&#xff0c;普通…

Python tikinter實現打開指定ip的電腦攝像頭

以下是一個使用Python的tkinter和OpenCV庫實現打開指定IP攝像頭的應用程序。這個程序允許用戶輸入IP攝像頭的URL&#xff0c;并實時顯示攝像頭畫面&#xff0c;同時支持截圖和錄制功能。 登錄后復制 import tkinter as tk from tkinter import ttk, messagebox, filedialog imp…

OpenCV插值方法詳解:原理、應用與代碼實踐

一、引言 在數字圖像處理中&#xff0c;插值是一種基本且重要的技術&#xff0c;它廣泛應用于圖像縮放、旋轉、幾何變換等場景。OpenCV作為最流行的計算機視覺庫之一&#xff0c;提供了多種插值方法供開發者選擇。本文將全面介紹OpenCV中的插值技術&#xff0c;包括各種方法的…

創客匠人解析:身心靈賽道創始人 IP 打造核心策略

在當代社會焦慮情緒蔓延的背景下&#xff0c;身心靈賽道正以萬億級市場規模成為知識變現的新藍海。作為知識變現領域的重要參與者&#xff0c;創客匠人通過服務超 5W 知識博主的實踐經驗&#xff0c;揭示了該賽道中創始人 IP 打造的底層邏輯 ——IP 不僅是形象符號&#xff0c…

Rust 和C++工業機器人實踐

Rust 調用Cursor案例 Cursor 的這些功能可以顯著提升開發效率,減少重復勞動,適合個人開發者和團隊協作使用。 讀取文件內容并處理 使用Cursor讀取文件內容并逐行處理: use std::io::{Cursor, BufRead};let data = "Line 1\nLine 2\nLine 3".as_bytes(); let c…

llama.cpp學習筆記:后端加載

單例 struct ggml_backend_registry {std::vector<ggml_backend_reg_entry> backends;std::vector<ggml_backend_dev_t> devices;// ... }struct ggml_backend_reg_entry {ggml_backend_reg_t reg;dl_handle_ptr handle; };typedef struct ggml_backend_reg * ggm…