JAVA之IO流

一    IO概述

概述

1、IO流:即InputOutput的縮寫。

2、特點:

        1)IO流用來處理設備間的數據傳輸。

        2)Java對數據的操作是通過流的方式。

        3)Java用於操作流的對象都在IO包中。

        4)流按操作數據分爲兩種:字節流和字符流。

        5)流按流向分爲:輸入流和輸出流。

注意:流只能操作數據,而不能操作文件。

3、IO流的常用基類:

        1)字節流的抽象基流:InputStream和OutputStream

        2)字符流的抽象基流:Reader和Writer

注:此四個類派生出來的子類名稱都是以父類名作爲子類名的後綴,以前綴爲其功能;如InputStream子類FileInputStream;Reader子類FileReader

 

二    字符流

一、簡述

        1、字符流中的對象融合了編碼表。使用的是默認的編碼,即當前系統的編碼。

        2、字符流只用於處理文字數據,而字節流可以處理媒體數據。

二、字符流的讀寫

1、寫入字符流步驟

        a、創建一個FileWriter對象,該對象一被初始化,就必須要明確被操作的文件。且該目錄下如果已有同名文件,則同名文件將被覆蓋。其實該步就是在明確數據要存放的目的地。

        b、調用write(String s)方法,將字符串寫入到流中。

        c、調用flush()方法,刷新該流的緩衝,將數據刷新到目的地中。

        d、調用close()方法,關閉流資源。但是關閉前會刷新一次內部的緩衝數據,並將數據刷新到目的地中。

close()和flush()區別:

        flush()刷新後,流可以繼續使用;

       而close()刷新後,將會關閉流,不可再寫入字符流。

注意:

        1、其實java自身不能寫入數據,而是調用系統內部方式完成數據的書寫,使用系統資源後,一定要關閉資源。

        2、文件的數據的續寫是通過構造函數 FileWriter(Strings,boolean append),在創建對象時,傳遞一個true參數,代表不覆蓋已有的文件。並在已有文件的末尾處進行數據續寫。(windows系統中的文件內換行用\r\n兩個轉義字符表示,在linux系統中只用\n表示換行)

        3、由於在創建對象時,需要指定創建文件位置,如果指定的位置不存在,就會發生IOException異常,所以在整個步驟中,需要對IO異常進行try處理。

 2、讀取字符流步驟

        1)創建一個文件讀取流對象,和指定名稱的文件相關聯。要保證該文件已經存在,若不存在,將會發生異常FileNotFoundException。

        2)調用讀取流對象的read()方法。read():一次讀一個字符,且會繼續往下讀。

              第一種方式:讀取單個字符。第二種方式:通過字符數組進行讀取。

        3)讀取後要調用close方法將流資源關閉。

注意:

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

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

        3、在讀取文件時,必須保證該文件已存在,否則出異常。
三、字符流的緩衝區——BufferedReader和BufferedWriter

1、緩衝區的出現:提高了流的讀寫效率,所以在緩衝區創建前,要先創建流對象。即先將流對象初始化到構造函數中。 

2、緩衝技術原理:此對象中封裝了數組,將數據存入,再一次性取出。

3、寫入流緩衝區BufferedWriter的步驟:

        1)創建一個字符寫入流對象。

         如:FileWriter fw=newFileWriter("buf.txt");

         2)爲了提高字符寫入流效率。加入緩衝技術。只要將需要被提高效率的流對象作爲參數傳遞給緩衝區的構造函數即可。

         如: BufferedWriter bufw =new BufferedWriter(fw);

         3)調用write方法寫入數據到指定文件

         如:bufw.write("adfg");

         記住,只要用到緩衝區,就要記得刷新。(關閉流同樣會刷新,但爲了排除意外事故,保證數據存在,建議寫入一次就刷新一次)

         如:bufw.flush();

         4)其實關閉緩衝區,就是在關閉緩衝區中的流對象。

        如: bufw.close();

4、讀取流緩衝區BufferedReader

        該緩衝區提供了一個一次讀一行的方法readLine,方便於堆文本數據的獲取,當返回null時表示讀到文件末尾。readLine方法返回的時候,只返回回車符之前的數據內容。並不返回回車符。

readLine方法原理:

        無論是讀一行。或者讀取多個字符。其實最終都是在在硬盤上一個一個讀取。所以最終使用的還是read方法一次讀一個的方法。

步驟:

        1)創建一個讀取流對象和文件相關聯

        如: FileReader fr=newFileReader("buf.txt");

        2)爲了提高效率。加入緩衝技術。將字符讀取流對象作爲參數傳遞給緩衝區對象的構造函數。

        如: BufferedReader bufr=new BufferedReader(fr);

        3)調用該緩衝區提供的readLine方法一行一行讀取,如果到達文件末尾,則返回null

        如: String s=bufr.readLine();

        4)關閉流資源

        如: bufr.close();、

5、自定義BufferedReader:

原理:

        可根據BufferedReader類中特有一行一行讀取方法readLine()的原理,自定義一個類中包含相同功能的方法

步驟:

        a、初始化自定義的類,加入流對象。

        b、定義一個臨時容器,原BufferedReader封裝的是字符數組,此類中可定義一個StringBuilder的容器,最終可實現字符串的提取。

6、LineNumberReader

        在BufferedReader中有個直接的子類LineNumberReader,其中有特有的方法獲取和設置行號:

         setLineNumber();//設置初始行號

         getLineNumber();//獲取行號

 

三     字節流

一、概述

1、字節流和字符流的基本操作是相同的,但字節流還可以操作其他媒體文件。

2、由於媒體文件數據中都是以字節存儲的,所以,字節流對象可直接對媒體文件的數據寫入到文件中,而可以不用再進行刷流動作。

3、讀寫字節流:InputStream   輸入流(讀)

                             OutputStream  輸出流(寫)

4、爲何不用進行刷流動作:

        因爲字節流操作的是字節,即數據的最小單位,不需要像字符流一樣要進行轉換爲字節。所以可直接將字節數據寫入到指定文件中。

5、InputStream特有方法:

        int available();//返回文件中的字節個數

注:可以利用此方法來指定讀取方式中傳入數組的長度,從而省去循環判斷。但是如果文件較大,而虛擬機啓動分配的默認內存一般爲64M。當文件過大時,此數組長度所佔內存空間就會溢出。所以,此方法慎用,當文件不大時,可以使用。

二、字節流緩衝區

        同樣是提高了字節流的讀寫效率。

1、讀寫特點:

        read():會將字節byte型值提升爲int型值

        write():會將int型強轉爲byte型,即保留二進制數的最後八位。

2、原理:將數據拷貝一部分,讀取一部分,循環,直到數據全部讀取完畢。

        1)先從數據中抓取固定數組長度的字節,存入定義的數組中,再通過然後再通過read()方法讀取數組中的元素,存入緩衝區。

        2)循環這個動作,直到最後取出一組數據存入數組,可能數組並未填滿,同樣也取出包含的元素。

        3)每次取出的時候,都有一個指針在移動,取到數組結尾就自動回到數組頭部,這樣指針在自增。

        4)取出的時候,數組中的元素在減少,取出一個,就減少一個,直到減到0即元素取完。

        5)當文件中的全部數據都被讀取出時,read()方法就返回-1。

3、自定義讀取字節流緩衝區

        需求:根據字節流緩衝區的原理,自定義一個字節流緩衝區。

注意:

        1、字節流的讀一個字節的read方法爲什麼返回值類型不是byte,而是int。

       因爲有可能會讀到連續8個二進制1的情況,8個二進制1對應的十進制是-1.那麼就會數據還沒有讀完,就結束的情況。因爲我們判斷讀取結束是通過結尾標記-1來確定的。

       所以,爲了避免這種情況將讀到的字節進行int類型的提升。並在保留原字節數據的情況前面了補了24個0,變成了int類型的數值。而在寫入數據時,只寫該int類型數據的最低8位。

        2、byte類型的-1提升爲int類型時還是-1。原因:因爲在bit8個1前面補的全是1導致的。如果在bit8個1前面補0,即可以保留原字節數據不變,又可以避免-1的出現。這時將byte型數據&0xff即255即可。

流的基本應用小結:

  • 流是用來處理數據的。
  • 處理數據時,一定要先明確數據源,與數據目的地(數據匯)。
  • 數據源可以是文件,可以是鍵盤。
  • 數據目的地可以是文件、顯示器或者其他設備。
  • 而流只是在幫助數據進行傳輸,並對傳輸的數據進行處理,比如過濾處理.轉換處理等。

字符流繼承體系簡圖

字節流繼承體系簡圖

 

四     File類

一、概述

1、File類:文件和目錄路徑名的抽象表現形式

2、特點:

        1)用來將文件或文件夾封裝成對象

        2)方便於對文件與文件夾的屬性信息進行操作

        3)File類的實例是不可變的;也就是說,一旦創建,File 對象表示的抽象路徑名將永不改變

        4)File對象可以作爲參數傳遞給流的構造函數

二、File對象創建

方式一:      

             File f =new File("a.txt");

        將a.txt封裝成File對象。可以將已有的和未出現的文件或者文件夾封裝成對象。

 方式二:

            File f2=newFile("c:\\abc","b.txt");

        將文件所在目錄路徑和文件一起傳入,指定文件路徑。

 方式三:

            File d=new File("c:\\abc");

             File f3=new File(d,"c.txt");

        將文件目錄路徑封裝成對象。再創建文件對象。降低了文件於父目錄的關聯性。

三、File類的常見方法

1、創建

        booleancreateNewFile();

        //在指定位置創建文件,如果該文件已經存在,則不創建,返回false。和輸出流不一樣,輸出流對象一建立就創建文件。而且文件已經存在,會覆蓋。

        boolean mkdir();//創建文件夾,只能創建一級文件夾

例:

        File dir=new File("abc");

        dir.mkdir();//創建abc這個文件夾

        boolean mkdirs();//創建多級文件夾

2、刪除

        boolean delete();

        //刪除文件或目錄。文件存在,返回true;文件不存在或者正在被執行,返回false。    

        void deleteOnExit();//在程序退出時刪除指定文件

3、判斷

        boolean canExecute();//是否是可執行文件

        boolean exists();//文件是否存在

        boolean isFile();//是否是文件

        boolean isDirectory();//是否是文件夾

        boolean isHidden();//是否是隱藏文件

        boolean isAbsolute();//文件是否是絕對路徑

記住:在判斷文件對象是否是文件或者目錄時,必須要判斷該文件對象封裝的內容是否存在。通過exists判斷。

4、獲取信息

        String getName();//獲取文件名

        String getPath();

        //獲取文件的相對路徑(即創建的對象傳入的參數是什麼就獲取到什麼)

        String getParent();

        //獲取文件父目錄。返回的是絕對路徑中的父目錄。如果獲取的是相對路徑,返回null。如果相對路徑中有上一層目錄,那麼該目錄就是返回結果。

        String getAbsolutePath();//獲取文件的絕對路徑      

        long lastModified();//返回文件最後一次被修改的時間

        long length();//返回文件長度

5、列出文件及文件過濾

        static File[] listRoots();//列出可用的文件系統根目錄

        String[] list();

        //列出當前目錄下所有文件,包括隱藏。調用list方法的file對象必須是封裝了一個目錄。該目錄還必須存在。

        String[]list(FilenameFilter filter);

        //返回一個字符串數組,獲取目錄中滿足指定過濾器的文件或目錄。

        //FilenameFilter:文件名過濾器,是一個接口,其中包含一個方法,accept(Filedir,String name),返回的是boolean型,對不符合條件的文件過濾掉。

        File[] listFiles();//返回一個抽象路徑名數組,獲取當前文件夾下的所有文件和文件夾

        File[] ListFiles(FilenameFilterfilter);//返回抽象路徑名數組,獲取目錄中滿足指定過濾器的文件或目錄。
四、遞歸

1、定義

       當函數內每一次循環還可以調用本功能來實現,也就是函數自身調用自身。這種表現形式,或者編程手法,稱爲遞歸。

2、遞歸注意事項

        a、限定條件。是來結束循環調用,否則是死循環。

        b、注意遞歸的次數,儘量避免內存溢出。因爲每次調用自身的時候都會先執行下一次調用自己的方法,所以會不斷在棧內存中開闢新空間,次數過多,會導致內存溢出。

 

五      Properties類

一、概述

1、Properties是Hashtable的子類,它具備Map集合的特點。而且它裏面還有存儲的鍵值對,都是字符串,無泛型定義。是集合中和IO技術想結合的集合容器。

2、特點:

        1)可用於鍵值對形式的配置文件

        2)在加載時,需要數據有固定的格式,常用的是:鍵=值

二、特有方法

1、設置

        Object setProperty(String key,String value);

        //設置鍵和值,調用Hashtable的方法put

2、獲取

        String getProperty(String key);

        //指定key搜索value

        Set<String> stringPropertyName();

        //返回屬性列表的鍵集,存入Set集合

3、加載流和存入流

        void load(InputStream ism);

        //從輸入字節流中讀取屬性列表(鍵和元素對)。又稱將流中的數據加載進集合。

        void load(Readerreader);

        //從輸入字符流中讀取屬性列表(鍵和元素對)。又稱將流中的數據加載進集合。

        voidlist(PrintStream out);//將屬性列表輸出到指定的輸出流

        void store(OutputStreamout,String comments);

        //對應load(InputStream )將屬性列表(鍵值對)寫入輸出流。comments屬性列表的描述。

        void store(Writerwriter, String comments);

        //對應load(Reader)將屬性列表(鍵值對)寫入輸出流。comments屬性列表的描述。

 

六    打印流

一、概述

        1、打印流包括:PrintStream和PrintWriter

        2、該流提供了打印方法,可將各種類型的數據都原樣打印。

二、字節打印流:PrintStream

構造方法中可接收的參數類型:

        1、File對象。File

        2、字符串路徑:String

        3、字符輸出流:OutputStream

三、字符串打印流:PrintWriter

構造方法中可接受的參數類型

        1、File對象:File

        2、字符串路徑:String

        3、字節輸出流:OutputStream

        4、字符輸出流:Writer

 

七    序列流

一、概述

1、SequenceInputStream對多個流進行合併。也被稱爲合併流。

2、常用構造函數

        SequenceInputStream(Enumeration<?extends FileInputStream> e)

二、常見合併多個流文件步驟

        1、創建集合,並將流對象添加進集合

        2、創建Enumeration對象,將集合元素加入。

        3、創建SequenceInputStream對象,合併流對象

        4、創建寫入流對象,FileOutputStream關聯寫入文件

        5、利用SequenceInputStream對象和FileOutputStream對象讀數據進行反覆讀寫操作。

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