天天看點

day18-字元流

1. 位元組流

1.1 位元組緩沖流概述和構造方法【應用】

  • 位元組緩沖流:
    • BufferedOutputStream:該類實作緩沖輸出流。通過設定這樣的輸出流,應用程式可以向底層輸出流寫入位元組,而不必為寫入的每個位元組導緻底層系統的調用
    • BufferedInputStream:建立BufferedInputStream将建立一個内部緩沖區數組。當從流中讀取或跳過位元組時,内部緩沖區将根據需要從所包含的輸入流中重新填充,一次很多位元組
  • 構造方法
    • 位元組緩沖輸出流:BufferedOutputStream(OutputStream out)
    • 位元組緩沖輸入流:BufferedInputStream(InputStream in)

為什麼構造方法需要的是位元組流,而不是具體的檔案或者路徑呢?

  • 子節緩沖流僅僅提供緩沖區,而真正的讀寫資料還得依靠基本的位元組流對象進行操作
  • 示範代碼
package com.day18;
/*
    位元組緩沖流:
        BufferedOutputStream
        BufferedInputStream
     構造方法:
        位元組緩沖輸出流:BufferedOutputStream(OutputStream out)
        位元組緩沖輸入流:BufferedInputStream(InputStream in)
 */

import java.io.*;

public class BufferStreamDemo {
    public static void main(String[] args) throws IOException {
//        位元組緩沖輸出流:BufferedOutputStream(OutputStream out)
        FileOutputStream fos = new FileOutputStream("idea_test\\bos.txt");
        BufferedOutputStream bos = new BufferedOutputStream(fos);
        //合并
        BufferedOutputStream bos1 = new BufferedOutputStream(new FileOutputStream("idea_test\\bos.txt"));
        //寫資料
        bos1.write("hello\r\n".getBytes());
        bos1.write("world\r\n".getBytes());
        //釋放資源
        bos1.close();
        bos.close();
//        位元組緩沖輸入流:BufferedInputStream(InputStream in)
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("idea_test\\bos.txt"));

        //讀資料
        //一次讀一個位元組資料
        int by;
        while ((by=bis.read())!=-1){
            System.out.print((char) by);
        }
        //一次讀取一個位元組數組資料
        byte[] bys = new byte[1024];
        //存儲位元組數組大小
        int len;
        while ((len = bis.read(bys)) != -1) {
            System.out.println(new String(bys, 0, len));
        }
        //釋放資源
        bis.close();
    }
}

           

1.2 複制視訊

  • 需求:把“E:\itcast\位元組流複制圖檔.avi’複制到子產品目錄下的”位元組流複制圖檔.vai"
  • 思路:
    • 根據資料源建立位元組輸入流對象
    • 根據目的地建立位元組輸出流對象
    • 讀寫資料,複制視訊
    • 釋放資源
  • 示範代碼
package com.day18;

import java.io.*;

/*
需求:把“E:\\itcast\\位元組流複制圖檔.avi'複制到子產品目錄下的”位元組流複制圖檔.vai"

 思路:
   根據資料源建立位元組輸入流對象
   根據目的地建立位元組輸出流對象
   讀寫資料,複制視訊
   釋放資源

   四種方式實作複雜視訊,并記錄每種方式複雜視訊的時間
        1:基本位元組流一次讀寫一個位元組  共耗時:220826毫秒
        2:基本位元組流一次讀寫一個位元組數組  333毫秒
        3:位元組緩沖流一次讀寫一個位元組  共耗時:833毫秒
        4:位元組緩沖流一次讀寫一個位元組數組  共耗時:65毫秒

 */
public class CopyAviDemo {
    public static void main(String[] args) throws IOException {
        //記錄開始時間
        long startTime = System.currentTimeMillis();

        //複雜視訊
        method1();
//        method2();
//        method3();
//        method4();

        //記錄結束時間
        long endTime = System.currentTimeMillis();
        System.out.println("共耗時:" + (endTime - startTime) + "毫秒");
    }

    //基本位元組流一次讀寫一個位元組  共耗時:220826毫秒
    private static void method1() throws IOException {
        //E:\\itcast\\位元組流複制圖檔.avi
        //複制到子產品目錄下的”位元組流複制圖檔.vai"
        FileInputStream fis = new FileInputStream("E:\\develop\\140_位元組流複制視訊.avi");
        FileOutputStream fos = new FileOutputStream("idea_test\\位元組流複制圖檔.avi");

        int by;
        while ((by = fis.read()) != -1) {
            fos.write(by);
        }
        fos.close();
        fis.close();
    }

    //基本位元組流一次讀寫一個位元組數組  333毫秒
    private static void method2() throws IOException {
        //E:\\itcast\\位元組流複制圖檔.avi
        //複制到子產品目錄下的”位元組流複制圖檔.vai"
        FileInputStream fis = new FileInputStream("E:\\develop\\140_位元組流複制視訊.avi");
        FileOutputStream fos = new FileOutputStream("idea_test\\位元組流複制圖檔.vai");

        byte[] bis = new byte[1024];
        int len;
        while ((len = fis.read(bis)) != -1) {
            fos.write(bis, 0, len);
        }

        fos.close();
        fis.close();
    }

    //    位元組緩沖流一次讀寫一個位元組  共耗時:833毫秒
    private static void method3() throws IOException {
        //E:\\itcast\\位元組流複制圖檔.avi
        //複制到子產品目錄下的”位元組流複制圖檔.vai"
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("E:\\develop\\140_位元組流複制視訊.avi"));
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("idea_test\\位元組流複制圖檔.vai"));

        int by;
        while ((by = bis.read()) != -1) {
            bos.write(by);
        }
        bos.close();
        bis.close();
    }

    //位元組緩沖流一次讀寫一個位元組數組  共耗時:65毫秒
    private static void method4() throws IOException {
        //E:\\itcast\\位元組流複制圖檔.avi
        //複制到子產品目錄下的”位元組流複制圖檔.vai"
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("E:\\develop\\140_位元組流複制視訊.avi"));
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("idea_test\\位元組流複制圖檔.vai"));

        byte[] bsy = new byte[1024];
        int len;
        while ((len = bis.read(bsy)) != -1) {
            bos.write(bsy, 0, len);
        }
        bos.close();
        bis.close();
    }
}

           
  • 基本位元組流一次讀寫一個位元組 共耗時:220826毫秒
  • 基本位元組流一次讀寫一個位元組數組 333毫秒
  • 位元組緩沖流一次讀寫一個位元組 共耗時:833毫秒
  • 位元組緩沖流一次讀寫一個位元組數組 共耗時:65毫秒

可以看出使用位元組緩沖流每次讀寫一個位元組數組是效率最高的

2. 字元流

為什麼要出現字元流呢?

  • 一個漢字的存儲
    • 如果是GBK編碼,占用2個位元組
    • 如果是UTF-8,占用3個位元組
  • 由于位元組流操作中文不是特别的友善,是以Java就提供字元流
    • 字元流=位元組流+編碼表

用位元組流傳輸文本檔案時,文本檔案也會有編碼,但是沒有問題,原因是最終底層操作會自動進行位元組拼接成中文,如何識别是中文的呢?

  • 漢字在存儲的時候,無論選擇哪種編碼存儲,第一個位元組都是負數

2.1 編碼表

基礎知識:

  • 計算機中儲存的資訊都是用二進制數表示的;我們在螢幕上看到的英文、漢字等字元是二進制數轉換之後的結果
  • 按照某種規則,将字元存儲到計算機中,稱為編碼。反之,将存儲在計算機中的二進制按照某種規則解析顯示出來,稱為解碼。這裡強調一下:按照A編碼存儲,必須按照A解析,這樣才能顯示正确的文本符合。否則就會導緻亂碼現象
  • 字元編碼:就是一套自然語言的字元與二進制數之間的對應規則(A,65)

ASCII字元集

  • ASCII(American Standard Code for Information Interchange,美國資訊交換标準代碼):是基于拉丁字母的一個電腦編碼系統,用于顯示現代英語,主要包括控制字元(Enter鍵、倒退、換行鍵等)和可顯示字元(英語大小寫字元、阿拉伯數字和西文符号)
  • 基本的ASCII字元集,使用7位表示一個字元,共128字元。ASCII的擴充字元集使用8位表示一個字元,共256字元,友善支援歐洲常用字元。是一個系統支援的所有字元的集合,包括各國文字、标點符号、圖形符号、數字等

GBXXX字元集

  • GB2312:簡體中文碼表。一個小于127的字元的意義與原來相同,但是兩個大于127的字元連在一起時,這樣大約可以組合了包含7000多個簡體漢字等。
  • GBK:最常用的中文碼表。是在GB2312标準上的擴充規格,使用了雙位元組編碼方案,共收錄了21003個漢字,完全相容GB2312标準,同時支援繁體漢字以及日韓漢字等
  • GB18030:最新的中文碼表。收錄漢字70244個,采用多位元組編碼,每個字可以由1個、2個或4個位元組組成。支援中國國内少數民族的文字,同時支援繁體漢字以及日韓漢字等

Unicode字元集

  • 為表示任意語言的任意而設計,業界的一種标準,也稱為統一碼、标準萬國碼。
  • UTF-8編碼:可以用來表示Unicode标準中任意字元,它是電子郵件、網頁及其他存儲或傳送文字的應用中,優先采用的編碼,網際網路工程工作小組(IETF)要求所有網際網路協定都必須支援UTF-8編碼。它使用一至四個位元組為每個字元編碼
    • 編碼規則:
      • 128 US-ASCI字元,隻需一個位元組編碼
      • 拉丁文等字元,需要二個位元組編碼,
      • 大部分常用字 (含中文) ,使用三個位元組編碼
      • 其他極少使用的Unicode輔助字元,使用四位元組編碼
  • 采用何種規則編碼,就要采用對應規則解碼,否則就會出現亂碼

2.2 字元串中的編碼解碼問題

編碼:

  • byte[] getBytes();使用平台的預設字元集将該String編碼為一系列,将結果存儲到新的位元組數組中
  • byte[] getBytes(String charsetName):使用指定的字元集将該String編碼為一系列位元組,将結果存儲到新的位元組數組中

解碼:

  • String(byte[] bytes);通過使用平台的預設字元解碼指定的位元組數組來構造新的String
  • String(byte[] bytes,String charsetName):通過指定的字元解碼指定的位元組數組來構造新的String
  • 示範代碼
package com.day18;

import java.io.UnsupportedEncodingException;
import java.util.Arrays;

public class StringDemo {
    public static void main(String[] args) throws UnsupportedEncodingException {
        String s="中國";
        byte[] bys = s.getBytes();//[-28, -72, -83, -27, -101, -67]
        byte[] bytes = s.getBytes("UTF-8");//[-28, -72, -83, -27, -101, -67]
        byte[] gbks = s.getBytes("GBK");//[-42, -48, -71, -6]
        byte[] gb2312s = s.getBytes("GB2312");//[-42, -48, -71, -6]
        System.out.println(Arrays.toString(gb2312s));
        //平台預設的解碼
        String s3 = new String(bys);//中國
        //錯誤的解碼
        String s1 = new String(bys,"GBK");//涓浗
        //正确的解碼
        String s2 = new String(bys, "UTF-8");//中國
        System.out.println(s3);
    }
}

           

采用何種規則編碼,就要采用對應規則解碼,否則就會出現亂碼

2.3 字元流中的編碼解碼問題

字元流抽象基類

  • Reader:字元輸入流的抽象類
  • Writer:字元輸出流的抽象類

字元流中和編碼解碼問題相關的兩個類

  • InputStreamReader
  • OutputStreamWriter
  • 示範代碼
package com.day18;

import java.io.*;

public class ConversionStreamDemo {
    public static void main(String[] args) throws IOException {
//        OutputStreamWriter​(OutputStream out) 建立一個使用預設字元編碼的OutputStreamWriter。
//        OutputStreamWriter​(OutputStream out, String charsetName) 建立一個使用命名字元集的OutputStreamWriter。
//        FileOutputStream fos = new FileOutputStream("idea_test\\osw.txt");
//        OutputStreamWriter osw =new OutputStreamWriter(fos);
//        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("idea_test\\osw.txt"));
//        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("idea_test\\osw.txt"), "UTF-8");
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("idea_test\\osw.txt"),"GBK");
        osw.write("中國");
        osw.close();
//        InputStreamReader​(InputStream in) 建立一個使用預設字元集的InputStreamReader。
//        InputStreamReader​(InputStream in, String charsetName) 建立一個使用命名字元集的InputStreamReader。
//        InputStreamReader isr = new InputStreamReader(new FileInputStream("idea_test\\osw.txt"));
        InputStreamReader isr = new InputStreamReader(new FileInputStream("idea_test\\osw.txt"),"GBK");
        //一次讀取一個字元資料
        int ch;
        while ((ch=isr.read())!=-1){
            System.out.print((char) ch);
        }
        //一次讀取一個字元數組
        char[] car= new char[1024];
        int len;
        while ((len=isr.read(car))!=-1){
            System.out.println(new String(car,0,len));
        }
        isr.close();
    }
}

           

采用何種規則編碼,就要采用對應規則解碼,否則就會出現亂碼

  • InputStreamReader
    • 構造方法
    • InputStreamReader​(InputStream in) 建立一個使用預設字元集的InputStreamReader。
    • InputStreamReader​(InputStream in, String charsetName) 建立一個使用命名字元集的InputStreamReader。
  • OutputStreamWriter
    • 構造方法
    • OutputStreamWriter​(OutputStream out) 建立一個使用預設字元編碼的OutputStreamWriter。
    • OutputStreamWriter​(OutputStream out, String charsetName) 建立一個使用命名字元集的OutputStreamWriter。

2.4 字元流寫資料的5種方法

方法名 說明
void write(int c) 寫一個字元
void write(char[] cbuf) 寫入一個字元數組
void write(char[] cbuf,int off,int len) 寫入字元數組的一部分
void write(String str) 寫一個字元串
void write(String str,int off,int len) 寫入一個字元串的一部分
  • 示範代碼
package com.day18;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;

public class OutputStreamWriterDemo {
    public static void main(String[] args) throws IOException {

        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("idea_test\\osw.txt"));
        //寫一個字元
        osw.write(97);
        osw.flush();
        osw.write(98);
        osw.flush();
        osw.write(99);
        //結果:abc

        //void write(char[] cbuf):寫入一個字元數組
        char[] chs = {'a', 'b', 'c', 'd', 'e'};
        osw.write(chs);
        //結果:abcde

        //void write(char[] cbuf, int off,int len):x寫入字元數組的一部分
        char[] chs1 = {'a', 'b', 'c', 'd', 'e'};
        osw.write(chs1, 0, 3);
        //結果:abc

        //void write(String str);寫一個字元串
        osw.write("abcse");
        //結果:abcse

        //void write(String str,int off,int len);寫一個字元串的一部分
        osw.write("abcde", 2, 2);
        //結果:cd

        //釋放資源
        osw.close();
        
        //java.io.IOException: Stream closed
//        osw.write(100);
    }
}

           

補充

方法名 說明
flush() 重新整理流,還可以繼續寫資料
close() 關閉流,釋放資源,但是在關閉之前會先重新整理流。一旦關閉,就不能再寫資料

2.5 字元流讀資料的2種方式

方法名 說明
int read() 一次讀一個字元資料
int read(char[] cbuf) 一次讀一個字元數組資料
  • 執行個體代碼
package com.day18;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;

public class InputStreamReaderDemo {
    public static void main(String[] args) throws IOException {
        InputStreamReader isr = new InputStreamReader(new FileInputStream("idea_test\\osw.txt"));
        //int read();一次讀一個字元資料
        int ch;
        while ((ch = isr.read()) != -1) {
            System.out.println((char) ch);
        }
        //int read(char[] cbuf);一次讀一個字元數組資料
        char[] chs=new char[1024];
        int len;
        while ((len=isr.read(chs))!=-1){
            System.out.print(new String(chs,0,len));
        }
        isr.close();
    }
}

           

2.6複制Java檔案

需求:把子產品目錄下的“ConversionStreamDemo.java" 複制子產品目錄下”Copr.java"

思路:

  • 根據資料源建立位元組輸入流對象
  • 根據目的地建立字元輸出流對象
  • 讀寫資料,複制檔案
  • 釋放資源
  • 示範代碼
package com.day18;

import java.io.*;

public class CopyJavaDemo01 {
    public static void main(String[] args) throws IOException {
        //根據資料源建立字元輸入對象
        InputStreamReader isr = new InputStreamReader(new FileInputStream("idea_test\\ConversionStreamDemo.java"));
        //根據目的地建立字元輸出對象
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("idea_test\\Copy.java"));
//        讀寫資料

        //一次讀寫一個字元資料
        int ch;
        while ((ch = isr.read()) != -1) {
            osw.write(ch);
        }
        //一次讀寫一個數組資料
        char[] car = new char[1024];
        int lne;
        while ((lne = isr.read(car)) != -1) {
            osw.write(car, 0, lne);
        }
        //釋放資源
        osw.close();
        isr.close();
    }
}

           

2.7複制Java檔案改造版

需求:把子產品目錄下的“ConversionStreamDemo.java" 複制子產品目錄下”Copr.java"

分析:

  • 轉換流的名字比較長,而我們常見的操作都是按照本地預設編碼實作的,是以,為了簡化書寫,轉換流提供了對應的子類
  • FileReader:用于讀取字元檔案的便捷類
    • FileReader(String fileName)
  • FileWriter:用于寫入字元檔案的便捷類
    • FileWriter(String fileName)
  • 資料源和目的地的分析
    • 資料源:idea_test\ConversionStreamDemo.java—讀資料—Reader—InputStreamReader–FileReader
    • 目的地:idea_test\Copy.java----寫資料–Writer—OutputStreamWriter—FileWriter

      在需要使用編碼轉換的時候,還是需要使用轉換類,即InputStreamReader\OutputStreamWriter

思路:

  • 根據資料源建立位元組輸入流對象
  • 根據目的地建立字元輸出流對象
  • 讀寫資料,複制檔案
  • 釋放資源
  • 示範代碼
package com.day18;

import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class CopyJavaDemo02 {
    public static void main(String[] args) throws IOException {
        //根據資料源建立字元輸入流對象
        FileReader fr = new FileReader("idea_test\\ConversionStreamDemo.java");
        //根據目的地建立字元輸出對象
        FileWriter fw = new FileWriter("idea_test\\Copy.java");
        //讀寫資料,複制檔案
        //每次讀取一個字元
        int ch;
        while ((ch = fr.read()) != -1) {
            fw.write(ch);
        }
        //每次讀取一個字元數組
        char[] car = new char[1024];
        int lne;
        while ((lne = fr.read(car)) != -1) {
            fw.write(car, 0, lne);
        }
        //釋放資源
        fw.close();
        fr.close();
    }
}

           

2.8字元緩沖流

字元緩沖流:

  • BufferedWriter:将文本寫入字元輸出流,緩沖字元,以提供單個字元,數組和字元串的高效寫入,可以指定緩沖區大小,或者可以接受預設大小。 預設值足夠大,可用于大多數用途。
  • BufferedReader:從字元輸入流讀取文本,緩沖字元,以提供字元,數組和行的高效讀取,可以指定緩沖區大小,或者可以使用預設大小。 預設值足夠大,可用于大多數用途。

構造方法

  • BufferedWriter(Writer out)
  • BufferedReader(Reader in)

-示範代碼

package com.day18;

import java.io.*;

public class BufferedStreamDemo01 {
    public static void main(String[] args) throws IOException {
//        FileWriter fw = new FileWriter("idea_test\\bw.txt");
//        BufferedWriter bufferedWriter = new BufferedWriter(fw);
        BufferedWriter bw = new BufferedWriter(new FileWriter("idea_test\\bw.txt"));
        //寫入資料
        bw.write("hello\r\n");
        bw.write("world\r\n");
        bw.close();

        BufferedReader br = new BufferedReader(new FileReader("idea_test\\bw.txt"));
        //一次讀取一個字元資料
        int ch;
        while ((ch = br.read()) != -1) {
            System.out.print((char) ch);
        }
        //一次讀取一個字元數組資料
        char[] car = new char[1024];
        int len;
        while ((len = br.read(car)) != -1) {
            System.out.print(new String(car, 0, len));
        }
        br.close();
    }
}

           

2.9 案例:複制Java檔案(字元緩沖流改進版)

需求:把子產品目錄下的“ConversionStreamDemo.java" 複制的子產品目錄下的"Copy.java"

思路:

  • 根據資料源建立字元緩沖輸入流對象
  • 根據目的地建立字元緩沖輸出流對象
  • 讀寫資料,複制檔案
  • 釋放資源
  • 代碼示範
package com.day18;

import java.io.*;

public class CopyJavaDemo03 {
    public static void main(String[] args) throws IOException {
        //建立緩沖輸入流
        BufferedReader br = new BufferedReader(new FileReader("idea_test\\ConversionStreamDemo.java"));
        //建立緩沖輸出流
        BufferedWriter bw = new BufferedWriter(new FileWriter("idea_test\\Copy.java"));
        //讀寫資料複制檔案
        //一次讀寫一個字元資料
        int ch;
        while ((ch = br.read()) != -1) {
            bw.write(ch);
        }
        //一次讀寫一個字元數組資料
        char[] car = new char[1024];
        int len;
        while ((len = br.read(car)) != -1) {
            bw.write(car, 0, len);
        }
        //釋放資源
        bw.close();
        br.close();
    }
}

           

2.10 字元緩沖流特有功能

  • BufferedWriter:
    • void newLine();寫一行行分隔符字元串由系統屬性定義
  • BufferedReader:
    • String readLine():讀一行文字。結果包含行的内容的字元串,不包括任何終止字元,如果流的結尾到達,則為null
  • 示範代碼
package com.day18;

import java.io.*;

public class BufferedStreamDemo02 {
    public static void main(String[] args) throws IOException {
       /* //建立字元緩沖流
        BufferedWriter bw = new BufferedWriter(new FileWriter("idea_test\\bw.txt"));

        //寫資料
        for (int i = 0; i < 10; i++) {
            bw.write("hello" + i);
//            bw.write("\r\n");
            bw.newLine();
            bw.flush();
        }
        bw.close();*/
        //建立字元緩沖輸入流
        BufferedReader br = new BufferedReader(new FileReader("idea_test\\bw.txt"));
        //hello0
        //第一次讀取資料
        String line = br.readLine();
        System.out.println(line);
        //hello1
        //第二次讀取資料
        line = br.readLine();
        System.out.println(line);
        //多讀兩行  null
        line = br.readLine();
        System.out.println(line);
        line = br.readLine();
        System.out.println(line);
        String lines;
        while ((lines = br.readLine()) != null) {
            //隻讀内容不讀換行符等内容,需要手動換行
            System.out.println(lines);
        }
        br.close();
    }
}

           

注意字元緩沖流(BufferedReader)的readLine隻讀資料不讀終止符(換行)

2.11 複制Java檔案(字元緩沖流特有功能改進版)

  • 需求:把子產品目錄下的“ConversionStreamDemo.java" 複制的子產品目錄下的"Copy.java"

思路:

  • 根據資料源建立字元緩沖輸入流對象
  • 根據目的地建立字元緩沖輸出流對象
  • 讀寫資料,複制檔案(使用字元緩沖流特有功能實作)
  • 釋放資源
  • 示範代碼
package com.day18;

import java.io.*;

public class CopyJavaDemo04 {
    public static void main(String[] args) throws IOException {
        //根據資料源建立字元緩沖輸入流對象
        BufferedReader br = new BufferedReader(new FileReader("idea_test\\ConversionStreamDemo.java"));
        //根據目的地建立字元緩沖輸出流對象
        BufferedWriter bw = new BufferedWriter(new FileWriter("idea_test\\Copy.java"));
        //讀寫資料,複制檔案
        //使用位元組緩沖流特有功能實作
        String line;
        while ((line = br.readLine()) != null) {
            bw.write(line);
            bw.newLine();
            bw.flush();
        }
        //釋放資源
        bw.close();
        br.close();
    }
}

           

注意使用readLine讀資料,需要使用BufferedWiter.newLine()換行處理

然後進行BufferedWiter.flush()刷空緩沖流

2.12 IO小節

  • 位元組流抽象類
    day18-字元流
  • 位元組流實作類
    day18-字元流
  • 字元流抽象類
    day18-字元流
  • 字元流實作類
    day18-字元流
    涉及編碼問題要使用InputStreamReader等

2.13 案例:集合到檔案

  • 需求:把ArrayList集合中的字元串資料寫入到文本檔案。要求:每個字元串元素作為檔案中的一行資料
  • 思路
    • 建立ArrayList集合
    • 往集合中存儲字元串元素
    • 建立字元緩沖輸出流對象
    • 周遊集合,得到每一個字元串資料
    • 調用字元緩沖輸出流對象的方法寫資料
    • 釋放資源
  • 示範代碼
package com.day18;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;

public class ArrayListToTxtDemo {
    public static void main(String[] args) throws IOException {
        //建立ArrayList集合
        ArrayList<String> arrayList = new ArrayList<>();

        //往集合中存儲字元串元素
        arrayList.add("hello");
        arrayList.add("world");
        arrayList.add("java");
        //建立字元緩沖輸出流對象
        BufferedWriter bw = new BufferedWriter(new FileWriter("idea_test\\bw.txt"));
        //周遊集合,得到每一個字元串資料
        for (String s : arrayList) {
            //調用字元緩沖輸出流對象的方法寫資料
            bw.write(s);
            bw.newLine();
            bw.flush();
        }
        //釋放資源
        bw.close();

    }
}

           

2.13 案例:檔案到集合

  • 需求:把文本檔案中的資料讀取到集合中,并周遊集合。要求:檔案中每一行資料是一個集合元素
  • 思路
    • 建立字元緩沖輸入流對象
    • 建立ArrayList集合對象
    • 調用字元緩沖流輸入流對象的方法讀資料
    • 把讀取到字元串資料儲存到集合中
    • 釋放資源
    • 周遊集合
  • 示範代碼
package com.day18;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;

public class TxtToArrayListDemo {
    public static void main(String[] args) throws IOException {
        //建立字元緩沖輸入流對象
        BufferedReader br = new BufferedReader(new FileReader("idea_test\\bw.txt"));
        //建立ArrayList集合對象
        ArrayList<String> arrayList = new ArrayList<>();
        //調用字元緩沖輸入流對象的方法讀資料
        String line;
        while ((line = br.readLine()) != null) {
            //把讀取到的字元串儲存到集合中
            arrayList.add(line);
        }
        //釋放資源
        br.close();
        //周遊集合
        for (String s : arrayList) {
            System.out.println(s);
        }
    }
}

           

2.14案例:點名器

  • 需求:我有一個檔案儲存了班級同學的姓名,每一個名字占一行,要求通過程式實作随機點名器
  • 思路
    • 建立位元組緩沖輸入流對象
    • 建立ArrayList集合對象
    • 調用字元緩沖輸入流對象的方法讀資料
    • 把讀取到的字元串儲存到集合中
    • 釋放資源
    • 使用Random生産一個随機數,随機數的範圍在:[0,集合的長度)
    • 把第6步産生的随機數作為索引到ArrayList集合中擷取值
    • 把第7步得到的資料輸出到控制台
  • 示範代碼
package com.day18;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Random;

/**
 * @author 61443
 */
public class CallNameDemo {
    public static void main(String[] args) throws IOException {
        //建立字元緩沖輸入流對象
        BufferedReader br = new BufferedReader(new FileReader("idea_test\\bw.txt"));
        //建立ArrayList集合對象
        ArrayList<String> arrayList = new ArrayList<>();
        //調用字元緩沖輸入流對象的方法讀資料
        String line;
        while ((line = br.readLine()) != null) {
            //把讀取到字元串資料存儲到集合中
            arrayList.add(line);
        }
        //釋放資源
        br.close();
        //使用Random産生一個随機數,随機數的範圍:[0,集合的長度)
        Random random = new Random();
        int anInt = random.nextInt(arrayList.size());
        //把産生的随機數作為索引到ArrayList集合中擷取值
        String s = arrayList.get(anInt);
        //把得到的随機輸出在控制台
        System.out.println(s);
    }
}

           

2.15案例:集合到檔案(改進版)

需求:把ArrayList集合中的學生資料到文本檔案。要求:每一個學生對象的資料作為檔案中的一行資料個格式:學号,姓名,年齡,居住地

舉例:itheima001,林青霞,30,西安

  • 思路:
    • 定義學生類
    • 建立ArrayList集合
    • 建立學生對象
    • 把學生對象添加到集合中
    • 建立字元緩沖輸出流對象
    • 周遊集合,得到每個學生對象
    • 把學生對象的資料拼接成指定格式的字元串
    • 調用字元緩沖輸出流對象的方法寫資料
    • 釋放資源
  • 示範代碼

學生類

package com.day18;

/**
 * @author 61443
 */
public class Student {

    private String sid;

    private String name;

    private int age;

    private String address;

    public Student(String sid, String name, int age, String address) {
        this.sid = sid;
        this.name = name;
        this.age = age;
        this.address = address;
    }

    public Student() {

    }

    public String getSid() {
        return sid;
    }

    public void setSid(String sid) {
        this.sid = sid;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Student student = (Student) o;

        if (age != student.age) return false;
        if (sid != null ? !sid.equals(student.sid) : student.sid != null) return false;
        if (name != null ? !name.equals(student.name) : student.name != null) return false;
        return address != null ? address.equals(student.address) : student.address == null;
    }

    @Override
    public int hashCode() {
        int result = sid != null ? sid.hashCode() : 0;
        result = 31 * result + (name != null ? name.hashCode() : 0);
        result = 31 * result + age;
        result = 31 * result + (address != null ? address.hashCode() : 0);
        return result;
    }

    @Override
    public String toString() {
        final StringBuffer sb = new StringBuffer("Student{");
        sb.append("sid='").append(sid).append('\'');
        sb.append(", name='").append(name).append('\'');
        sb.append(", age=").append(age);
        sb.append(", address='").append(address).append('\'');
        sb.append('}');
        return sb.toString();
    }
}

           

測試類

package com.day18;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;

public class ArrayListToFileDemo {
    public static void main(String[] args) throws IOException {
//        建立ArrayList集合
        ArrayList<Student> arrayList = new ArrayList<>();
        //        建立學生對象
        Student s1 = new Student("itheima011", "林青霞", 30, "西安");
        Student s2 = new Student("itheima012", "林青霞", 30, "西安");
        Student s3 = new Student("itheima013", "林青霞", 30, "西安");
//        把學生對象添加到集合中
        arrayList.add(s1);
        arrayList.add(s2);
        arrayList.add(s3);
//        建立字元緩沖輸出流對象
        BufferedWriter bw = new BufferedWriter(new FileWriter("idea_test\\osw.txt"));
//        周遊集合,得到每個學生對象
        for (Student student : arrayList) {
//            把學生對象的資料拼接成指定格式的字元串
            StringBuilder builder = new StringBuilder();
            builder.append(student.getSid()).append(",").append(student.getName()).append(",").append(student.getAge()).append(",").append(student.getAddress());
//            調用字元緩沖輸出流對象的方法寫資料
            bw.write(builder.toString());
            bw.newLine();
            bw.flush();
        }
//        釋放資源
        bw.close();
    }
}

           

2.15案例:集合到檔案(改進版)

  • 需求:把文本檔案中的資料讀取到集合中,并周遊集合。要求:檔案中每一行資料是一個學生對象的成員變量值 舉例:itheima001,林青霞,30.西安
  • 思路:
    • 定義學生類
    • 建立字元緩沖輸入流對象
    • 建立ArrayList集合對象
    • 調用字元緩沖輸入流對象的方法讀資料
    • 把讀取到字元串資料用split() 進行分割,得到一個字元串數組
    • 建立學生對象
    • 把字元串數組中的每一個元素取出來對應的指派給學生對象的成員變量值
    • 把學生對象添加到集合
    • 周遊集合
  • 示範代碼

學生類

package com.day18;

/**
 * @author 61443
 */
public class Student {

    private String sid;

    private String name;

    private int age;

    private String address;

    public Student(String sid, String name, int age, String address) {
        this.sid = sid;
        this.name = name;
        this.age = age;
        this.address = address;
    }

    public Student() {

    }

    public String getSid() {
        return sid;
    }

    public void setSid(String sid) {
        this.sid = sid;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Student student = (Student) o;

        if (age != student.age) return false;
        if (sid != null ? !sid.equals(student.sid) : student.sid != null) return false;
        if (name != null ? !name.equals(student.name) : student.name != null) return false;
        return address != null ? address.equals(student.address) : student.address == null;
    }

    @Override
    public int hashCode() {
        int result = sid != null ? sid.hashCode() : 0;
        result = 31 * result + (name != null ? name.hashCode() : 0);
        result = 31 * result + age;
        result = 31 * result + (address != null ? address.hashCode() : 0);
        return result;
    }

    @Override
    public String toString() {
        final StringBuffer sb = new StringBuffer("Student{");
        sb.append("sid='").append(sid).append('\'');
        sb.append(", name='").append(name).append('\'');
        sb.append(", age=").append(age);
        sb.append(", address='").append(address).append('\'');
        sb.append('}');
        return sb.toString();
    }
}

           

測試類

package com.day18;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;

public class FileToArrayListDemo {
    public static void main(String[] args) throws IOException {
        //建立字元緩沖輸入流對象
        BufferedReader br = new BufferedReader(new FileReader("idea_test\\osw.txt"));
//        建立ArrayList集合對象
        ArrayList<Student> list = new ArrayList<>();
        //調用字元緩沖輸入流對象的方法讀資料
        String line;
        while ((line = br.readLine()) != null) {
            //把讀取到字元串資料用split() 進行分割,得到一個字元串數組
            String[] split = line.split(",");
            //建立學生對象
            Student student = new Student();
//            把字元串數組中的每一個元素取出來對應的指派給學生對象的成員變量值
            student.setSid(split[0]);
            student.setName(split[1]);
            student.setAge(Integer.valueOf(split[2]));
            student.setAddress(split[3]);
            //把學生對象添加到集合
            list.add(student);
        }
        //釋放資源
        br.close();
        //周遊集合
        for (Student s : list) {
            System.out.println(s.getSid() + "," + s.getName() + "," + s.getAge() + "," + s.getAddress());
        }
    }
}

           

繼續閱讀