1. 程式人生 > 實用技巧 >轉換流、緩衝流

轉換流、緩衝流

轉換流,,,,, 緩衝流,,,,,Properties類,,,,,序列化流與反序列化流

轉換流

1. OutputStreamWriter類

它的作用的就是,將字串按照指定的編碼表轉成位元組,在使用位元組流將這些位元組寫出去。

public static void writeCN() throws Exception {
        //建立與檔案關聯的位元組輸出流物件
        FileOutputStream fos = new FileOutputStream("c:\\cn8.txt");
        //建立可以把字元轉成位元組的轉換流物件,並指定編碼
        OutputStreamWriter osw = new OutputStreamWriter(fos,"utf-8");
        //呼叫轉換流,把文字寫出去,其實是寫到轉換流的緩衝區中
        osw.write("你好");//寫入緩衝區。
        osw.close();
    }

2. InputStreamReader類

InputStreamReader 是位元組流通向字元流的橋樑:它使用指定的字元編碼表讀取位元組並將其解碼為字元。

它使用的字符集可以由名稱指定或顯式給定,或者可以接受平臺預設的字符集。

public class InputStreamReaderDemo {
    public static void main(String[] args) throws IOException {
        //演示位元組轉字元流的轉換流
        readCN();
    }
    public static void readCN() throws IOException{
        //建立讀取檔案的位元組流物件
        InputStream in = new FileInputStream("c:\\cn8.txt");
        //建立轉換流物件 
        //InputStreamReader isr = new InputStreamReader(in);這樣建立物件,會用本地預設碼錶讀取,將會發生錯誤解碼的錯誤
        InputStreamReader isr = new InputStreamReader(in,"utf-8");
        //使用轉換流去讀位元組流中的位元組
        int ch = 0;
        while((ch = isr.read())!=-1){
            System.out.println((char)ch);
        }
        //關閉流
        isr.close();
    }
}

緩衝流

1 位元組緩衝流

位元組緩衝流根據流的方向,共有2個

l 寫入資料到流中,位元組緩衝輸出流 BufferedOutputStream

l 讀取流中的資料,位元組緩衝輸入流 BufferedInputStream

1.1 位元組緩衝輸出流BufferedOutputStream

1.2 位元組緩衝輸入流 BufferedInputStream

public static void main(String[] args) throws IOException {
    FileInputStream shuru=new FileInputStream("D:\\表約束.wmv");
    //建立位元組輸出緩衝流
    BufferedInputStream bis=new BufferedInputStream(shuru);
    //建立位元組輸出流
    FileOutputStream shuchu=new FileOutputStream("D:\\io0512\\a\\字元流.wmv");
    //建立位元組輸出
    BufferedOutputStream bos=new BufferedOutputStream(shuchu);
    //複製
    int len=0;
    while((len=bis.read())!=-1){
        bos.write(len);
    }
    bis.close();
    bos.close();
}

2 字元緩衝流

l 字元緩衝輸入流 BufferedReader

l 字元緩衝輸出流 BufferedWriter

完成文字資料的高效的寫入與讀取的操作

字元緩衝輸出流 BufferedWriter

l 方法:

void newLine() 根據當前的系統,寫入一個換行符

public class BufferedWriterDemo {
    public static void main(String[] args) throws IOException {
        //建立流
        //基本字元輸出流
        FileWriter fileOut = new FileWriter("file.txt");
        //把基本的流進行包裝
        BufferedWriter out = new BufferedWriter(fileOut);
        //2,寫資料
        for (int i=0; i<5; i++) {
            out.write("hello");
            out.newLine();
        }
        //3,關閉流
        out.close();
    }
}

字元緩衝輸入流 BufferedReader

l 方法

publicStringreadLine() 讀取一個文字行,包含該行內容的字串,不包含任何行終止符,如果已到達流末尾,則返回 null

public class BufferedReaderDemo {
    public static void main(String[] args) throws IOException {
        //1,建立流
        BufferedReader in = new BufferedReader(new FileReader("file.txt"));
        //2,讀資料
        //一次一個字元
        //一次一個字元陣列
        //一次讀取文字中一行的字串內容
        String line = null;
        while( (line = in.readLine()) != null ){
            System.out.println(line);
        }
        
        //3,關閉流
        in.close();
    }
}

文字複製,一個字元陣列一個數組讀

public class Demo04 {
public static void main(String[] args) throws IOException {
    //建立字元輸入
    FileReader shuru=new FileReader("D:\\io0512\\utf-8.txt");
    BufferedReader br=new BufferedReader(shuru);
    FileWriter shuchu=new FileWriter("D:\\io0512\\a\\utf-8.txt");
    BufferedWriter bw=new BufferedWriter(shuchu);
    int len=0;
    char[] ch=new char[2];
    while((len=br.read(ch))!=-1){
        bw.write(ch,0,len);
        bw.flush();
    }
    br.close();
    bw.close();
}
}

一個位元組一個位元組複製

public static void main(String[] args) throws IOException {
    FileInputStream shuru=new FileInputStream("D:\\表約束.wmv");
    //建立位元組輸出緩衝流
    BufferedInputStream bis=new BufferedInputStream(shuru);
    //建立位元組輸出流
    FileOutputStream shuchu=new FileOutputStream("D:\\io0512\\a\\字元流.wmv");
    //建立位元組輸出
    BufferedOutputStream bos=new BufferedOutputStream(shuchu);
    //複製
    int len=0;
    while((len=bis.read())!=-1){
        bos.write(len);
    }
    bis.close();
    bos.close();
}
}

一行一行的讀

public static void main(String[] args) throws IOException {
    //chuang減字元輸入流
    FileReader shuru=new FileReader("D:\\io0512\\utf-8.txt");
    
    BufferedReader br=new BufferedReader(shuru);
    FileWriter shuchu=new FileWriter("D:\\io0512\\utf-82.txt");
    BufferedWriter bw=new BufferedWriter(shuchu);
    //複製
    String len=null;
    while((len=br.readLine())!=null){//一行一行讀
        bw.write(len);
        bw.newLine();//換行
        bw.flush();
    }
    br.close();
    bw.close();
}

流的操作規律

IO流中物件很多,解決問題(處理裝置上的資料時)到底該用哪個物件呢?  

把IO流進行了規律的總結(四個明確):

l 明確一:要操作的資料是資料來源還是資料目的。

源:InputStream Reader

目的:OutputStream Writer

先根據需求明確要讀,還是要寫。

l 明確二:要操作的資料是位元組還是文字呢?

源:

位元組:InputStream

文字:Reader

目的:

位元組:OutputStream

文字:Writer

已經明確到了具體的體系上。

l 明確三:明確資料所在的具體裝置。

源裝置:

硬碟:檔案 File開頭。

記憶體:陣列,字串。

鍵盤:System.in;

網路:Socket

目的裝置:

硬碟:檔案 File開頭。

記憶體:陣列,字串。

螢幕:System.out

網路:Socket

完全可以明確具體要使用哪個流物件。

l 明確四:是否需要額外功能呢?

額外功能:

轉換嗎?轉換流。InputStreamReader OutputStreamWriter

高效嗎?緩衝區物件。BufferedXXX

InputStream

FileInputStream

BufferedInputStream

OuputStream

FileOutputStream

BufferedOuputStream

Writer

OutputStreamWriter

FileWriter

BufferedWriter

Reader

InputStreamReader

FileReader

BufferedReader

Properties類

Properties類表示了一個持久的屬性集。Properties可儲存在流中或從流中載入。屬性列表中每個鍵及其對應值都是一個字串。

特點:

1、Hashtable的子類,map集合中的方法都可以用。

2、該集合沒有泛型。鍵值都是字串。

3、它是一個可以持久化的屬性集。鍵值可以儲存到集合中,也可以儲存到持久化的裝置(硬碟、U盤、光碟)上。鍵值的來源也可以是持久化的裝置。

4、有和流技術相結合的方法。

public static void main(String[] args) {
    //建立Pro集合
    Properties pro=new Properties();
    pro.put("a", "18");//存值
    pro.put("b", "16");
    System.out.println(pro.getProperty("a"));//輸出18,取值
    System.out.println(pro.getProperty("b"));//輸出16
}

public static void main(String[] args) throws IOException {
    Properties pro=new Properties();//建立Propertues物件
    pro.put("name","Amy");
    pro.put("age", "19");
//明確properties的路徑 FileOutputStream fos=new FileOutputStream("src/com/oracle/demo02/pro.properties",true); pro.store(fos, "");//註釋,註釋不寫顯示當前時間 }

l load(InputStream) 把指定流所對應的檔案中的資料,讀取出來,儲存到Propertie集合中

l load(Reader)

l store(OutputStream,commonts)把集合中的資料,儲存到指定的流所對應的檔案中,引數commonts代表對描述資訊

l stroe(Writer,comments);

load讀取

序列化流與反序列化流

建立物件的方式:一種是new,一種是物件序列化

ObjectOutputStream 將 Java 物件的基本資料型別和圖形寫入 OutputStream。可以使用 ObjectInputStream 讀取(重構)物件。通過在流中使用檔案可以實現物件的持久儲存。

序列化:將一個物件封裝到檔案中(ObjectOutputStream)

//序列化
public class Demo01 {//將一個物件封存到檔案中
public static void main(String[] args) throws IOException {
    //明確目的地
    FileOutputStream fos=new FileOutputStream("D:\\io0512\\person.txt");
    //建立序列化流
    ObjectOutputStream oos=new ObjectOutputStream(fos);
    oos.writeObject(new Person("張三",20));
    oos.close();
}
}

反序列化:將封裝好的檔案讀出來(ObjectInputStream)

用於從流中讀取物件的

//反序列化
public class Demo02 {//將封存的對向讀回來
public static void main(String[] args) throws ClassNotFoundException, IOException {
    //明確資料來源
    FileInputStream fis=new FileInputStream("D:\\io0512\\person.txt");
    //建立反序列化流物件
    ObjectInputStream ois=new ObjectInputStream(fis);
    //讀取物件
    Person p=(Person)ois.readObject();
    System.out.println(p);//列印存好的資訊,Person【name=張三,age=18】
    ois.close();
}
}

Person類

public class Person implements Serializable{//序列化介面
public static String name;//靜態修飾不屬於物件,屬於類,不被序列化(序列化是物件)
private transient int age;//不需要被序列化的屬性可以加transient,就不被序列化,寫的值就不能被讀出來
//定死uid的序列化號,保證txt和person裡的序列號一致
private static final long serialVersionUID=123L;//序列化號

public String toString() {
    return "Person [name=" + name + ", age=" + age + "]";
}
public Person(String name, int age) {
    super();
    this.name = name;
    this.age = age;
}
public Person() {
    super();
}
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;
}

}

序列化介面

當一個物件要能被序列化,這個物件所屬的類必須實現Serializable介面。否則會發生異常NotSerializableException異常。

同時當反序列化物件時,如果物件所屬的class檔案在序列化之後進行的修改,那麼進行反序列化也會發生異常InvalidClassException。發生這個異常的原因如下:

l 該類的序列版本號與從流中讀取的類描述符的版本號不匹配

l 該類包含未知資料型別

l 該類沒有可訪問的無引數構造方法

Serializable標記介面。該介面給需要序列化的類,提供了一個序列版本號。serialVersionUID. 該版本號的目的在於驗證序列化的物件和對應類是否版本匹配。

瞬態關鍵字transient

當一個類的物件需要被序列化時,某些屬性不需要被序列化,這時不需要序列化的屬性可以使用關鍵字transient修飾。只要被transient修飾了,序列化時這個屬性就不會序列化了。

同時靜態修飾也不會被序列化,因為序列化是把物件資料進行持久化儲存,而靜態的屬於類載入時的資料,不會被序列化。

不被序列化就無法寫入資料,讀取到的是預設值