一篇 java IO流學習文章 (上)

IO流上:概述、字符流、緩衝區(java基礎)



一、IO流概述

概述:

IO流簡單來說就是Input和Output流,IO流主要是用來處理設備之間的數據傳輸, java對於數據的操作都是通過流實現,而java用於操作流的對象都在IO包中。


分類:

    按操作數據分爲:字節流和字符流。 如:Reader和InpurStream

    按流向分:輸入流和輸出流。如:InputStream和OutputStream

IO流常用的基類:

     * InputStream    ,    OutputStream

字符流的抽象基類:

     * Reader       ,         Writer

由上面四個類派生的子類名稱都是以其父類名作爲子類的後綴:

        如:FileReader和FileInputStream

二、字符流

1. 字符流簡介:

  • 字符流中的對象融合了編碼表,也就是系統默認的編碼表。我們的系統一般都是GBK編碼。

  • 字符流只用來處理文本數據,字節流用來處理媒體數據。

  • 數據最常見的表現方式是文件,字符流用於操作文件的子類一般是FileReader和FileWriter。

2.字符流讀寫:

注意事項:

  • 寫入文件後必須要用flush()刷新。

  • 用完流後記得要關閉流

  • 使用流對象要拋出IO異常

  • 定義文件路徑時,可以用“/”或者“\”。

  • 在創建一個文件時,如果目錄下有同名文件將被覆蓋。

  • 在讀取文件時,必須保證該文件已存在,否則出異常


示例1:在硬盤上創建一個文件,並寫入一些文字數據
class FireWriterDemo {  
    public static void main(String[] args) throws IOException {             //需要對IO異常進行處理   

        //創建一個FileWriter對象,該對象一被初始化就必須要明確被操作的文件。  
        //而且該文件會被創建到指定目錄下。如果該目錄有同名文件,那麼該文件將被覆蓋。  

        FileWriter fw = new FileWriter("F:\\1.txt");//目的是明確數據要存放的目的地。  

        //調用write的方法將字符串寫到流中  
        fw.write("hello world!");  

        //刷新流對象緩衝中的數據,將數據刷到目的地中  
        fw.flush();  

        //關閉流資源,但是關閉之前會刷新一次內部緩衝中的數據。當我們結束輸入時候,必須close();  
        fw.write("first_test");  
        fw.close();  
        //flush和close的區別:flush刷新後可以繼續輸入,close刷新後不能繼續輸入。  

    }  
}  

示例2:FileReader的reade()方法.

要求:用單個字符和字符數組進行分別讀取

class FileReaderDemo {  
    public static void main(String[] args) {  
        characters();  
    }  


/*****************字符數組進行讀取*********************/  
    private static void characters() {  

        try {  

            FileReader fr = new FileReader("Demo.txt");  
            char []  buf = new char[6];   
            //將Denmo中的文件讀取到buf數組中。  
            int num = 0;      
            while((num = fr.read(buf))!=-1) {  

                //String(char[] value , int offest,int count) 分配一個新的String,包含從offest開始的count個字符  
                sop(new String(buf,0,num));  
            }  
            sop('\n');  
            fr.close();  
        }  
        catch (IOException e) {  
            sop(e.toString());  
        }  
    }  






/*****************單個字母讀取*************************/  
    private static void singleReader() {  

        try {  

            //創建一個文件讀取流對象,和指定名稱的文件關聯。  
            //要保證文件已經存在,否則會發生異常:FileNotFoundException  
            FileReader fr = new FileReader("Demo.txt");  


            //如何調用讀取流對象的read方法?  
            //read()方法,一次讀取一個字符,並且自動往下讀。如果到達末尾則返回-1  
            int ch = 0;  
            while ((ch=fr.read())!=-1) {  
                sop((char)ch);  
            }  
            sop('\n');  
            fr.close();  


            /*int ch = fr.read(); 
            sop("ch=" + (char)ch); 

            int ch2 = fr.read(); 
            sop("ch2=" + (char)ch2); 

            //使用結束注意關閉流 
            fr.close(); */    



        }  
        catch (IOException e) {  
            sop(e.toString());  
        }  

    }  


/**********************Println************************/  
    private static void sop(Object obj) {  
        System.out.print(obj);  
    }  

}  

示例3:對已有文件的數據進行續寫

import java.io.*;  

class  FileWriterDemo3 {  
    public static void main(String[] args) {  

        try {  
            //傳遞一個參數,代表不覆蓋已有的數據。並在已有數據的末尾進行數據續寫  
            FileWriter fw = new FileWriter("F:\\java_Demo\\day9_24\\demo.txt",true);  
            fw.write(" is charactor table?");  
            fw.close();  
        }  
        catch (IOException e) {  
            sop(e.toString());  
        }  

    }  

/**********************Println************************/  
    private static void sop(Object obj)  
    {  
        System.out.println(obj);  
    }  
}  

練習:

將F盤的一個文件複製到E盤。

思考:

其實就是將F盤下的文件數據存儲到D盤的一個文件中。

步驟:

1.在D盤創建一個文件,存儲F盤中文件的數據。
2.定義讀取流和F:盤文件關聯。
3.通過不斷讀寫完成數據存儲。
4.關閉資源。

源碼:

import java.io.*;  
import java.util.Scanner;  

class CopyText {  
    public static void main(String[] args) throws IOException {  
        sop("請輸入要拷貝的文件的路徑:");  
        Scanner in = new Scanner(System.in);  
        String source = in.next();  
        sop("請輸入需要拷貝到那個位置的路徑以及生成的文件名:");  
        String destination = in.next();  
        in.close();  
        CopyTextDemo(source,destination);  

    }  

/*****************文件Copy*********************/  
    private static void CopyTextDemo(String source,String destination) {  

        try {  
            FileWriter fw = new FileWriter(destination);  
            FileReader fr = new FileReader(source);  
            char []  buf = new char[1024];   
            //將Denmo中的文件讀取到buf數組中。  
            int num = 0;      
            while((num = fr.read(buf))!=-1) {  
                               //String(char[] value , int offest,int count) 分配一個新的String,包含從offest開始的count個字符  
                fw.write(new String(buf,0,num));  
            }  
            fr.close();  
            fw.close();  
        }  
        catch (IOException e) {  
            sop(e.toString());  
        }  
    }  



/**********************Println************************/  
    private static void sop(Object obj) {  
        System.out.println(obj);  
    }  
}  

三、緩衝區

1. 字符流的緩衝區:BufferedReader和BufferedWreiter

  • 緩衝區的出現時爲了提高流的操作效率而出現的.

  • 需要被提高效率的流作爲參數傳遞給緩衝區的構造函數

  • 在緩衝區中封裝了一個數組,存入數據後一次取出


BufferedReader示例:

讀取流緩衝區提供了一個一次讀一行的方法readline,方便對文本數據的獲取。
readline()只返回回車符前面的字符,不返回回車符。如果是複製的話,必須加入 newLine(),寫入回車符

newLine()是java提供的多平臺換行符寫入方法。

import java.io.*;  


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

        //創建一個字符讀取流流對象,和文件關聯  
        FileReader rw = new FileReader("buf.txt");  

        //只要將需要被提高效率的流作爲參數傳遞給緩衝區的構造函數即可  
        BufferedReader brw = new BufferedReader(rw);  


        for(;;) {  
            String s = brw.readLine();  
            if(s==null) break;  
            System.out.println(s);  
        }  

        brw.close();//關閉輸入流對象  

    }  
}  

BufferedWriter示例:

import java.io.*;  


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

        //創建一個字符寫入流對象  
        FileWriter fw = new FileWriter("buf.txt");  

        //爲了提高字符寫入效率,加入了緩衝技術。  
        //只要將需要被提高效率的流作爲參數傳遞給緩衝區的構造函數即可  
        BufferedWriter bfw = new BufferedWriter(fw);  

        //bfw.write("abc\r\nde");  
        //bfw.newLine();               這行代碼等價於bfw.write("\r\n"),相當於一個跨平臺的換行符  
        //用到緩衝區就必須要刷新  
        for(int x = 1; x < 5; x++) {  
            bfw.write("abc");  
            bfw.newLine();                  //java提供了一個跨平臺的換行符newLine();  
            bfw.flush();  
        }  



        bfw.flush();                                                //刷新緩衝區  
        bfw.close();                                                //關閉緩衝區,但是必須要先刷新  

        //注意,關閉緩衝區就是在關閉緩衝中的流對象  
        fw.close();                                                 //關閉輸入流對象  

    }  
}  

2.裝飾設計模式

裝飾設計模式:

要求:自定義一些Reader類,讀取不同的數據(裝飾和繼承的區別)
MyReader //專門用於讀取數據的類
|–MyTextReader
   |–MyBufferTextReader
|–MyMediaReader
    |–MyBufferMediaReader
|–MyDataReader
    |–MyBufferDataReader

如果將他們抽取出來,設計一個MyBufferReader,可以根據傳入的類型進行增強

ass MyBufferReader {

MyBufferReader (MyTextReader text) { }
MyBufferReader (MyMediaReader media) { }
MyBufferReader (MyDataReader data) { }

}

但是上面的類拓展性很差。找到其參數的共同類型,通過多態的形式,可以提高拓展性

class MyBufferReader  extends MyReader{
    private MyReader r;                        //從繼承變爲了組成模式  裝飾設計模式
    MyBufferReader(MyReader r) {}
}

優化後的體系:
|–MyTextReader
|–MyMediaReader
|–MyDataReader
|–MyBufferReader //增強上面三個。裝飾模式比繼承靈活,
避免繼承體系的臃腫。降低類與類之間的耦合性

裝飾類只能增強已有的對象,具備的功能是相同的。所以裝飾類和被裝飾類屬於同一個體系

MyBuffereReader類: 自己寫一個MyBuffereReader類,功能與BuffereReader相同

class MyBufferedReader1  extends Reader{               
    private Reader r;  
    MyBufferedReader1(Reader r){  
        this.r  = r;  
    }  

    //一次讀一行數據的方法  
    public String myReaderline()  throws IOException {  
        //定義一個臨時容器,原BufferReader封裝的是字符數組。  
        //爲了演示方便。定義一個StringBuilder容器。最終要將數據變成字符串  
        StringBuilder sb = new StringBuilder();  
        int ch = 0;  
        while((ch = r.read()) != -1)  
        {  
            if(ch == '\r')   
                continue;  
            if(ch == '\n')                    //遇到換行符\n,返回字符串  
                return sb.toString();  
            else  
            sb.append((char)ch);  
        }  
        if(sb.length()!=0)                    //當最後一行不是以\n結束時候,這裏需要判斷  
            return sb.toString();  
        return null;  
    }  
    /* 
    需要覆蓋Reader中的抽象方法close(),read(); 
    */  
    public void close()throws IOException {  
        r.close();  
    }  

    public int read(char[] cbuf,int off, int len)throws IOException {   //覆蓋read方法  
        return r.read(cbuf,off,len);  
    }  

    public void myClose() throws IOException{  
        r.close();  
    }  


}  

轉載自:
https://www.cnblogs.com/xll1025/p/6418766.htmlc
https://blog.csdn.net/u010041075/article/details/49007731

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章