日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 >

Java笔记整理六(File类,递归,字节流IO,字符流IO,流中的异常处理,属性集Properties,缓冲流,转换流,序列化,打印流)

發(fā)布時間:2023/12/15 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java笔记整理六(File类,递归,字节流IO,字符流IO,流中的异常处理,属性集Properties,缓冲流,转换流,序列化,打印流) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

1.File類

java.io.File 類是文件和目錄路徑名的抽象表示,主要用于文件和目錄的創(chuàng)建、查找和刪除等操作。

文件和目錄路徑名的抽象表示

java把文件和文件夾封裝位為一個File類,我們可以用File類的對文件和文件夾進(jìn)行操作

使用File類我們可以

  • 創(chuàng)建一個文件夾/文件
  • 刪除文件/文件夾
  • 獲取文件/文件夾
  • 判斷文件/文件夾是否存在
  • 獲取文件大小

File是一個與系統(tǒng)無關(guān)的類,任何系統(tǒng)都可以使用這個類中的方法。

重點(diǎn):
file:文件
directory:目錄
path:路徑

static String pathSeparator:路徑分隔符
static char pathSeparator:路徑分隔符

Srting pathSeparator=File.pathSeparator; windows:分號 linux:冒號

static String separator:默認(rèn)名稱分隔符
static char separator:默認(rèn)名稱分隔符

Srting separator=File.separator; windows:\ linux:/

路徑不能寫死了
“c:“+File.separator+”develop“+File.separator+a.txt”

絕對路徑,相對路徑

絕對路徑:完整路徑c:\a.txt
相對路徑:簡化路徑,相對當(dāng)前項目的根目錄

注意:

  • 路徑不區(qū)分大小寫
  • 路徑中文件名稱分隔符windows使用雙反斜杠
  • File中的構(gòu)造方法

    • public File(String pathname) :通過將給定的路徑名字符串轉(zhuǎn)換為抽象路徑名來創(chuàng)建新的 File實(shí)例。
      可以是以文件/文件夾結(jié)尾。可以相對路徑也可以是絕對路徑,可以是存在的也可以不存在。創(chuàng)建File對象,只把字符串路徑封裝給File對象,不考慮路徑對象 它重寫了File的toString方法。

    • public File(String parent, String child) :從父路徑名字符串和子路徑名字符串創(chuàng)建新的 File實(shí)例。
      父路徑和子路徑,可以單獨(dú)書寫,使用靈活

    • public File(File parent, String child) :從父抽象路徑名和子路徑名字符串創(chuàng)建新的 File實(shí)例。
      父路徑和子路徑,可以單獨(dú)書寫,使用靈活,父路徑是File類型,可以使用File的方法對路徑進(jìn)行一些操作,再使用路徑創(chuàng)建對象

    獲取功能的方法

    • public String getAbsolutePath() :返回此File的絕對路徑名字符串。

    • public String getPath() :將此File轉(zhuǎn)換為路徑名字符串。

    • public String getName() :返回由此File表示的文件或目錄的名稱。

    • public long length() :返回由此File表示的文件的長度。

      方法演示,代碼如下:

    public class FileGet {public static void main(String[] args) {File f = new File("d:/aaa/bbb.java"); System.out.println("文件絕對路徑:"+f.getAbsolutePath());System.out.println("文件構(gòu)造路徑:"+f.getPath());System.out.println("文件名稱:"+f.getName());System.out.println("文件長度:"+f.length()+"字節(jié)");File f2 = new File("d:/aaa"); System.out.println("目錄絕對路徑:"+f2.getAbsolutePath());System.out.println("目錄構(gòu)造路徑:"+f2.getPath());System.out.println("目錄名稱:"+f2.getName());System.out.println("目錄長度:"+f2.length());}}輸出結(jié)果:文件絕對路徑:d:\aaa\bbb.java文件構(gòu)造路徑:d:\aaa\bbb.java文件名稱:bbb.java文件長度:636字節(jié)目錄絕對路徑:d:\aaa目錄構(gòu)造路徑:d:\aaa目錄名稱:aaa目錄長度:4096

    判斷功能的方法

    • public boolean exists() :此File表示的文件或目錄是否實(shí)際存在。
    • public boolean isDirectory() :此File表示的是否為目錄。
    • public boolean isFile() :此File表示的是否為文件。

    方法演示,代碼如下:

    public class FileIs {public static void main(String[] args) {File f = new File("d:\\aaa\\bbb.java");File f2 = new File("d:\\aaa");// 判斷是否存在System.out.println("d:\\aaa\\bbb.java 是否存在:"+f.exists());System.out.println("d:\\aaa 是否存在:"+f2.exists());// 判斷是文件還是目錄System.out.println("d:\\aaa 文件?:"+f2.isFile());System.out.println("d:\\aaa 目錄?:"+f2.isDirectory());} } 輸出結(jié)果: d:\aaa\bbb.java 是否存在:true d:\aaa 是否存在:true d:\aaa 文件?:false d:\aaa 目錄?:true

    創(chuàng)建刪除功能的方法

    • public boolean createNewFile() :當(dāng)且僅當(dāng)具有該名稱的文件尚不存在時,創(chuàng)建一個新的空文件。 只能創(chuàng)建文件。不能創(chuàng)建文件夾。需要處理異常,必須路徑存在,否則會拋出io異常。

    • public boolean delete() :刪除由此File表示的文件或目錄。 不走回收站

    • 文件/文件夾刪除成功,返回true

    • 文件夾有內(nèi)容不回刪除,返回false,構(gòu)造方法中不存在也返回false

    • public boolean mkdir() :創(chuàng)建由此File表示的目錄。只能創(chuàng)建單集空文件夾
    • public boolean mkdirs() :創(chuàng)建由此File表示的目錄,包括任何必需但不存在的父目錄。可以創(chuàng)建單級文件夾也可以創(chuàng)建多級空文件夾。
    • 返回值:true:文件夾不存在,創(chuàng)建文件夾,返回true
      返回false:文件夾存在,不會創(chuàng)建,構(gòu)造方法中給出的路徑不存在也返回false
      只能創(chuàng)建文件夾不能創(chuàng)建文件
      創(chuàng)建文件的路徑必須存在,否則會拋出異常

    方法演示,代碼如下:

    public class FileCreateDelete {public static void main(String[] args) throws IOException {// 文件的創(chuàng)建File f = new File("aaa.txt");System.out.println("是否存在:"+f.exists()); // falseSystem.out.println("是否創(chuàng)建:"+f.createNewFile()); // trueSystem.out.println("是否存在:"+f.exists()); // true// 目錄的創(chuàng)建File f2= new File("newDir"); System.out.println("是否存在:"+f2.exists());// falseSystem.out.println("是否創(chuàng)建:"+f2.mkdir()); // trueSystem.out.println("是否存在:"+f2.exists());// true// 創(chuàng)建多級目錄File f3= new File("newDira\\newDirb");System.out.println(f3.mkdir());// falseFile f4= new File("newDira\\newDirb");System.out.println(f4.mkdirs());// true// 文件的刪除System.out.println(f.delete());// true// 目錄的刪除System.out.println(f2.delete());// trueSystem.out.println(f4.delete());// false} }

    API中說明:delete方法,如果此File表示目錄,則目錄必須為空才能刪除。

    目錄的遍歷

    • public String[] list() :返回一個String數(shù)組,表示該File目錄中的所有子文件或目錄。把獲取到的多個名稱存儲到一個String類型的數(shù)組中。

    • public File[] listFiles() :返回一個File數(shù)組,表示該File目錄中的所有的子文件或目錄。遍歷構(gòu)造方法中給出的目錄,獲取所有文件或文件夾的名稱,把獲取到的多個名稱存儲到一個String類型的數(shù)組中

    list和listFiles方法遍歷的是構(gòu)造方法中給出的目錄
    如果走早方法中給出路徑不存在,會拋出空指針異常
    如果構(gòu)造方法中給出的路徑不是一個目錄,會拋出空指針異常

    public class FileFor {public static void main(String[] args) {File dir = new File("d:\\java_code");//獲取當(dāng)前目錄下的文件以及文件夾的名稱。String[] names = dir.list();for(String name : names){System.out.println(name);}//獲取當(dāng)前目錄下的文件以及文件夾對象,只要拿到了文件對象,那么就可以獲取更多信息File[] files = dir.listFiles();for (File file : files) {System.out.println(file);}} }

    小貼士:

    調(diào)用listFiles方法的File對象,表示的必須是實(shí)際存在的目錄,否則返回null,無法進(jìn)行遍歷。

    遞歸

    遞歸:指再當(dāng)前方法體調(diào)用自己

    分為直接遞歸和間接遞歸
    注意事項:

    • 遞歸一定要有條件限制,保證遞歸能夠停止
    • 遞歸次數(shù)不能太多,否則可能會發(fā)生棧內(nèi)存溢出
    • 構(gòu)造方法禁止遞歸

    遞歸方法使用前提:
    當(dāng)調(diào)用方法的時候,方法主體不變,每次調(diào)用方法的參數(shù)不同,可以使用遞歸

    使用遞歸計算1–n的和

    使用遞歸必須明確:

  • 遞歸的結(jié)束條件:獲取到一結(jié)束
  • 遞歸的目的:獲取下一個被加的數(shù)字
  • 實(shí)現(xiàn)代碼

    public class DiGuiDemo {public static void main(String[] args) {//計算1~num的和,使用遞歸完成int num = 5;// 調(diào)用求和的方法int sum = getSum(num);// 輸出結(jié)果System.out.println(sum);}/*通過遞歸算法實(shí)現(xiàn).參數(shù)列表:int 返回值類型: int */public static int getSum(int num) {/* num為1時,方法返回1,相當(dāng)于是方法的出口,num總有是1的情況*/if(num == 1){return 1;}/*num不為1時,方法返回 num +(num-1)的累和遞歸調(diào)用getSum方法*/return num + getSum(num-1);} }

    遞歸求階乘

    階乘:所有小于及等于該數(shù)的正整數(shù)的積。

    n的階乘:n! = n * (n-1) *...* 3 * 2 * 1 推理得出:n! = n * (n-1)!

    代碼實(shí)現(xiàn)

    public class DiGuiDemo {//計算n的階乘,使用遞歸完成public static void main(String[] args) {int n = 3;// 調(diào)用求階乘的方法int value = getValue(n);// 輸出結(jié)果System.out.println("階乘為:"+ value);}/*通過遞歸算法實(shí)現(xiàn).參數(shù)列表:int 返回值類型: int */public static int getValue(int n) {// 1的階乘為1if (n == 1) {return 1;}/*n不為1時,方法返回 n! = n*(n-1)!遞歸調(diào)用getValue方法*/return n * getValue(n - 1);} }

    遞歸打印多級目錄

    分析:多級目錄的打印,就是當(dāng)目錄的嵌套。遍歷之前,無從知道到底有多少級目錄,所以我們還是要使用遞歸實(shí)現(xiàn)。

    代碼實(shí)現(xiàn)

    public class DiGuiDemo2 {public static void main(String[] args) {// 創(chuàng)建File對象File dir = new File("D:\\aaa");// 調(diào)用打印目錄方法printDir(dir);}public static void printDir(File dir) {// 獲取子文件和目錄File[] files = dir.listFiles();// 循環(huán)打印/*判斷:當(dāng)是文件時,打印絕對路徑.當(dāng)是目錄時,繼續(xù)調(diào)用打印目錄的方法,形成遞歸調(diào)用.*/for (File file : files) {// 判斷if (file.isFile()) {// 是文件,輸出文件絕對路徑System.out.println("文件名:"+ file.getAbsolutePath());} else {// 是目錄,輸出目錄絕對路徑System.out.println("目錄:"+file.getAbsolutePath());// 繼續(xù)遍歷,調(diào)用printDir,形成遞歸printDir(file);}}} }

    文件搜索

    搜索D:\aaa 目錄中的.java 文件。

    分析

  • 目錄搜索,無法判斷多少級目錄,所以使用遞歸,遍歷所有目錄。
  • 遍歷目錄時,獲取的子文件,通過文件名稱,判斷是否符合條件。
  • 代碼實(shí)現(xiàn)

    public class DiGuiDemo3 {public static void main(String[] args) {// 創(chuàng)建File對象File dir = new File("D:\\aaa");// 調(diào)用打印目錄方法printDir(dir);}public static void printDir(File dir) {// 獲取子文件和目錄File[] files = dir.listFiles();// 循環(huán)打印for (File file : files) {if (file.isFile()) {// 是文件,判斷文件名并輸出文件絕對路徑if (file.getName().endsWith(".java")) {System.out.println("文件名:" + file.getAbsolutePath());}} else {// 是目錄,繼續(xù)遍歷,形成遞歸printDir(file);}}} }

    文件過濾器優(yōu)化

    listFiles(FileFilter fileter)
    File類中有兩個和ListFiles重載的方法,方法參數(shù)就是過濾器

    java.io.FileFilter是一個接口,是File的過濾器。 該接口的對象可以傳遞給File類的
    用于抽象路徑名(File對象)的過濾器,用來過濾文件
    boolean accept(File pathname) :測試pathname是否應(yīng)該包含在當(dāng)前File目錄中,符合則返回true。

    listFiles(FilenameFilter fileter) :
    java.io.FilenameFilter接口:實(shí)現(xiàn)此接口的類實(shí)例可用于過濾器文件名
    用于過濾文件名稱
    boolean accept(File dir ,String name) :測試文件是否包含在某一文件夾中

    File dir:構(gòu)造方法中傳遞的被遍歷的目錄
    String name::使用ListFiles方法遍歷目錄,獲取的每一個文件/文件夾的名稱

    注意:兩個過濾器接口是沒有實(shí)現(xiàn)類的,需要我們自己寫實(shí)現(xiàn)類,重寫過濾方法accep,在方法中自己定義過濾器規(guī)則。

    分析

  • 接口作為參數(shù),需要傳遞子類對象,重寫其中方法。我們選擇匿名內(nèi)部類方式,比較簡單。
  • accept方法,參數(shù)為File,表示當(dāng)前File下所有的子文件和子目錄。保留住則返回true,過濾掉則返回false。保留規(guī)則:
  • 要么是.java文件。
  • 要么是目錄,用于繼續(xù)遍歷。
  • 通過過濾器的作用,listFiles(FileFilter)返回的數(shù)組元素中,子文件對象都是符合條件的,可以直接打印。
  • 代碼實(shí)現(xiàn):

    public class DiGuiDemo4 {public static void main(String[] args) {File dir = new File("D:\\aaa");printDir2(dir);}public static void printDir2(File dir) {// 匿名內(nèi)部類方式,創(chuàng)建過濾器子類對象File[] files = dir.listFiles(new FileFilter() {@Overridepublic boolean accept(File pathname) {return pathname.getName().endsWith(".java")||pathname.isDirectory();}});// 循環(huán)打印for (File file : files) {if (file.isFile()) {System.out.println("文件名:" + file.getAbsolutePath());} else {printDir2(file);}}} }

    FileFilter過濾器的原理和使用

    必須明確兩件事情:

  • 過濾器中accept方法是誰調(diào)用的,
  • accept方法的參數(shù)pathname是什么。
    ListFiles方法一共做了三件事情:
  • ListFiles方法對構(gòu)造中傳遞的目錄進(jìn)行遍歷,獲取目錄中的每一個文件夾/文件----封裝成File對象
  • ListFiles方法會調(diào)用參數(shù)傳遞的過濾器中的方法accept
  • listFiles方法會把遍歷的到的File對象,傳遞過accept方法的參數(shù)pathname
  • accept方法返回的是一個boolean值
    true: 會把傳遞過去的File對象保存到File數(shù)組中
    false:就不會把傳遞過去的File對象保存到File數(shù)組中

    因此,過濾的規(guī)則:
    在accept方法中,判斷File對象

    Lambda優(yōu)化

    分析:FileFilter是只有一個方法的接口,因此可以用lambda表達(dá)式簡寫。

    lambda格式:

    ()->{ }

    代碼實(shí)現(xiàn):

    public static void printDir3(File dir) {// lambda的改寫File[] files = dir.listFiles(f ->{ return f.getName().endsWith(".java") || f.isDirectory(); });// 循環(huán)打印for (File file : files) {if (file.isFile()) {System.out.println("文件名:" + file.getAbsolutePath());} else {printDir3(file);}} }

    IO

    IO的分類

    根據(jù)數(shù)據(jù)的流向分為:輸入流輸出流

    • 輸入流 :把數(shù)據(jù)從其他設(shè)備上讀取到內(nèi)存中的流。
    • 輸出流 :把數(shù)據(jù)從內(nèi)存 中寫出到其他設(shè)備上的流。

    格局?jǐn)?shù)據(jù)的類型分為:字節(jié)流字符流

    • 字節(jié)流 :以字節(jié)為單位,讀寫數(shù)據(jù)的流。
    • 字符流 :以字符為單位,讀寫數(shù)據(jù)的流。

    流:數(shù)據(jù)(字符,字節(jié))一個字符=兩個字節(jié)
    一個字節(jié)=八個二進(jìn)制(八位)

    ::輸入流輸出流
    字節(jié)流字節(jié)輸入流
    InputStream
    字節(jié)輸出流
    OutputStream
    字符流字符輸入流
    Reader
    字符輸出流
    Writer

    IO字節(jié)流

    以二進(jìn)制數(shù)字的形式保存,都一個一個的字節(jié),那么傳輸時一樣如此

    字節(jié)輸出流OutputStream

    java.io.OutputStream抽象類是表示字節(jié)輸出流的所有類的超類,將指定的字節(jié)信息寫出到目的地。它定義了字節(jié)輸出流的基本共性功能方法。

    • public void close() :關(guān)閉此輸出流并釋放與此流相關(guān)聯(lián)的任何系統(tǒng)資源。
    • public void flush() :刷新此輸出流并強(qiáng)制任何緩沖的輸出字節(jié)被寫出。
    • public void write(byte[] b):將 b.length字節(jié)從指定的字節(jié)數(shù)組寫入此輸出流。
    • public void write(byte[] b, int off, int len) :從指定的字節(jié)數(shù)組寫入 len字節(jié),從偏移量 off開始輸出到此輸出流。
    • public abstract void write(int b) :將指定的字節(jié)輸出流。

    close方法,當(dāng)完成流的操作時,必須調(diào)用此方法,釋放系統(tǒng)資源。

    FileOutputStream類:文件輸出流

    java.io.FileOutputStream類是文件輸出流,用于將內(nèi)存數(shù)據(jù)寫出到硬盤的文件中。

    構(gòu)造方法

    • public FileOutputStream(File file):創(chuàng)建文件輸出流以寫入由指定的 File對象表示的文件。
    • public FileOutputStream(String name): 創(chuàng)建文件輸出流以指定的名稱寫入文件。

    參數(shù):寫入數(shù)據(jù)的目的地。
    String name文件路徑
    File file:目的地是一個文件
    構(gòu)造方法地作用:
    1.創(chuàng)建一個 FileOutputStream對象
    2.會根據(jù)構(gòu)造方法中傳遞的文件/文件路徑,創(chuàng)建一個空的文件
    3.會把 FileOutputStream對象指向創(chuàng)建好的問文件

    字節(jié)流寫入數(shù)據(jù)到文件

    寫出字節(jié)
    寫入數(shù)據(jù)的原理:(內(nèi)存–>硬盤)
    java程序—>JVM(Java虛擬機(jī))—>Os(操作系統(tǒng))—>OS調(diào)用寫數(shù)據(jù)的方法—>把數(shù)據(jù)寫入到文件中

    字節(jié)輸出流的使用步驟:

  • 創(chuàng)建一個 FileOutputStream對象,構(gòu)造方法中傳遞寫入的數(shù)據(jù)的目的地
  • 調(diào)用 FileOutputStream對象中的方法write,把數(shù)據(jù)寫入到文件中
  • 釋放資源(流使用會占用一定的內(nèi)存,使用完畢要把內(nèi)存清空,提供程序的效率)
  • 需要拋出異常

    public class FOSWrite {public static void main(String[] args) throws IOException {// 使用文件名稱創(chuàng)建流對象FileOutputStream fos = new FileOutputStream("fos.txt"); // 寫出數(shù)據(jù)fos.write(97); // 寫出第1個字節(jié)fos.write(98); // 寫出第2個字節(jié)fos.write(99); // 寫出第3個字節(jié)// 關(guān)閉資源fos.close();} } 輸出結(jié)果: abc

    寫數(shù)據(jù)的時候,會把10進(jìn)制的整數(shù)轉(zhuǎn)換為二進(jìn)制整數(shù)97
    當(dāng)你創(chuàng)建一個流對象時,必須傳入一個文件路徑。該路徑下,如果沒有這個文件,會創(chuàng)建該文件。如果有這個文件,會清空這個文件的數(shù)據(jù)。

    寫出字節(jié)數(shù)組:write(byte[] b),
    一次寫多個字節(jié)

  • 創(chuàng)建 FileOutputStream對象, 構(gòu)造方法中綁定要寫入的數(shù)據(jù)的目的地
  • 調(diào)用 FileOutputStream對象中的方法write(byte[] b)(如果第一個字節(jié)是正數(shù)(0–127 ),那么顯示的時候會查詢ascii表 ,如果第一個字節(jié)是負(fù)數(shù),那么第一個字節(jié)會和第二個字節(jié),兩個字節(jié)組成 一個中文顯示,查詢系統(tǒng)默認(rèn)碼表(GBK)),把數(shù)據(jù)寫入到文本中.
  • 釋放資源
  • public class FOSWrite {public static void main(String[] args) throws IOException {// 使用文件名稱創(chuàng)建流對象FileOutputStream fos = new FileOutputStream("fos.txt"); // 字符串轉(zhuǎn)換為字節(jié)數(shù)組byte[] b = "黑馬程序員".getBytes();// 寫出字節(jié)數(shù)組數(shù)據(jù)fos.write(b);// 關(guān)閉資源fos.close();} }

    寫出指定長度字節(jié)數(shù)組:write(byte[] b, int off, int len) ,每次寫出從off索引開始,len個字節(jié)。把字節(jié)數(shù)組的一部寫入到文件中

    .getBytes()把字符串轉(zhuǎn)換為字節(jié)數(shù)組
    arrays.toString(字節(jié)數(shù)組)轉(zhuǎn)換為十進(jìn)制數(shù)組

    public class FOSWrite {public static void main(String[] args) throws IOException {// 使用文件名稱創(chuàng)建流對象FileOutputStream fos = new FileOutputStream("fos.txt"); // 字符串轉(zhuǎn)換為字節(jié)數(shù)組byte[] b = "abcde".getBytes();// 寫出從索引2開始,2個字節(jié)。索引2是c,兩個字節(jié),也就是cd。fos.write(b,2,2);// 關(guān)閉資源fos.close();} } 輸出結(jié)果: cd

    數(shù)據(jù)追加續(xù)寫

    ** 追加寫**:使用兩個參數(shù)的構(gòu)造方法

    • public FileOutputStream(File file, boolean append): 創(chuàng)建文件輸出流以寫入由指定的 File對象表示的文件。
      -創(chuàng)建一個向指定File對象表示的文件中寫入數(shù)據(jù)的文件輸出流

    • public FileOutputStream(String name, boolean append): 創(chuàng)建文件輸出流以指定的名稱寫入文件

    • 創(chuàng)建一個向具有指定name的文件中寫入數(shù)據(jù)的輸出文件流

    String 那么,File file:寫入數(shù)據(jù)的目的地
    boolean append:追加寫開關(guān)

    true:創(chuàng)建對象不回覆蓋原文件,繼續(xù)在文件的末尾追加寫數(shù)據(jù)
    false:創(chuàng)建一個新文件,覆蓋原文件

    寫換行:寫換行符號
    windows:\r\n
    linux: /n
    mac:/r

    public class FOSWrite {public static void main(String[] args) throws IOException {// 使用文件名稱創(chuàng)建流對象FileOutputStream fos = new FileOutputStream("fos.txt"); // 定義字節(jié)數(shù)組byte[] words = {97,98,99,100,101};// 遍歷數(shù)組for (int i = 0; i < words.length; i++) {// 寫出一個字節(jié)fos.write(words[i]);// 寫出一個換行, 換行符號轉(zhuǎn)成數(shù)組寫出fos.write("\r\n".getBytes());}// 關(guān)閉資源fos.close();} }輸出結(jié)果: a b c d e

    字節(jié)輸入流InputStream

    java.io.InputStream抽象類是表示字節(jié)輸入流的所有類的超類,可以讀取字節(jié)信息到內(nèi)存中。它定義了字節(jié)輸入流的基本共性功能方法。

    所有子類共性的方法:

    • public void close() :關(guān)閉此輸入流并釋放與此流相關(guān)聯(lián)的任何系統(tǒng)資源。

    • public abstract int read(): 從輸入流讀取數(shù)據(jù)的下一個字節(jié)。

    • public int read(byte[] b): 從輸入流中讀取一些字節(jié)數(shù),并將它們存儲到字節(jié)數(shù)組 b中 。

    close方法,當(dāng)完成流的操作時,必須調(diào)用此方法,釋放系統(tǒng)資源。

    FileInputStream類

    作用:把硬盤中的文件數(shù)據(jù),讀取到內(nèi)存中使用
    構(gòu)造方法

    • FileInputStream(File file): 通過打開與實(shí)際文件的連接來創(chuàng)建一個 FileInputStream ,該文件由文件系統(tǒng)中的 File對象 file命名。

    • FileInputStream(String name): 通過打開與實(shí)際文件的連接來創(chuàng)建一個 FileInputStream ,該文件由文件系統(tǒng)中的路徑名 name命名。

    當(dāng)你創(chuàng)建一個流對象時,必須傳入一個文件路徑。該路徑下,如果沒有該文件,會拋出FileNotFoundException 。

    參數(shù):讀取文件的數(shù)據(jù)源
    String name:文件路徑
    File file:文件

    構(gòu)造方法的作用:
    1.會創(chuàng)建一個FileInputStream對象
    2.會把FileInputStream對象指定給構(gòu)造方法中讀取的文件

    讀取數(shù)據(jù)的原理(硬盤–>內(nèi)存)
    java程序 -->JVM -->OS–>OS讀取數(shù)據(jù)的方法–>讀取文件
    自己輸入流的使用步驟(重點(diǎn)):

  • 創(chuàng)建FileInputStream對象,構(gòu)造方法中綁定要讀取的數(shù)據(jù)源。
  • 使用FileInputStream對象中的方法read,讀取文件
  • 釋放文件
  • 讀取字節(jié)數(shù)據(jù)

  • 讀取字節(jié):read方法,每次可以讀取一個字節(jié)的數(shù)據(jù),提升為int類型,讀取到文件末尾,返回-1,代碼使用演示:
  • 每次讀取一個字節(jié)

    public class FISRead {public static void main(String[] args) throws IOException{// 使用文件名稱創(chuàng)建流對象FileInputStream fis = new FileInputStream("read.txt");// 讀取數(shù)據(jù),返回一個字節(jié)int read = fis.read();System.out.println((char) read);read = fis.read();System.out.println((char) read);read = fis.read();System.out.println((char) read);read = fis.read();System.out.println((char) read);read = fis.read();System.out.println((char) read);// 讀取到末尾,返回-1read = fis.read();System.out.println( read);// 關(guān)閉資源fis.close();} } 輸出結(jié)果: a b c d e -1

    循環(huán)改進(jìn)讀取方式,代碼使用演示:
    不知道文件有多少字節(jié),使用while循環(huán)
    結(jié)束條件:讀取到-1的時候

    public class FISRead {public static void main(String[] args) throws IOException{// 使用文件名稱創(chuàng)建流對象FileInputStream fis = new FileInputStream("read.txt");// 定義變量,保存數(shù)據(jù)int b ;// 循環(huán)讀取,必須用變量接收while ((b = fis.read())!=-1) {System.out.println((char)b);}// 關(guān)閉資源fis.close();} } 輸出結(jié)果: a b c d e

    . 使用字節(jié)數(shù)組讀取:read(byte[] b),每次讀取b的長度個字節(jié)到數(shù)組中,返回讀取到的有效字節(jié)個數(shù),讀取到末尾時,返回-1 ,:

    public class FISRead {public static void main(String[] args) throws IOException{// 使用文件名稱創(chuàng)建流對象.FileInputStream fis = new FileInputStream("read.txt"); // 文件中為abcde// 定義變量,作為有效個數(shù)int len ;// 定義字節(jié)數(shù)組,作為裝字節(jié)數(shù)據(jù)的容器 byte[] b = new byte[2];// 循環(huán)讀取while (( len= fis.read(b))!=-1) {// 每次讀取后,把數(shù)組的有效字節(jié)部分,變成字符串打印System.out.println(new String(b,0,len));// len 每次讀取的有效字節(jié)個數(shù)}// 關(guān)閉資源fis.close();} }輸出結(jié)果: ab cd e

    一次讀取多個字節(jié)
    原理:
    1.創(chuàng)建一個流對象,并把它指向要讀取的文件
    2.創(chuàng)建一個byte數(shù)組
    3.讀取數(shù)據(jù)

    • 讀取數(shù)組長度大小的數(shù)據(jù)
    • 返回有效讀取字節(jié)個數(shù)

    數(shù)組起到緩沖作用,存儲讀取到的多個字節(jié) 一般定義為1024的整數(shù)倍

    字節(jié)流練習(xí):圖片復(fù)制

    文件復(fù)制:一讀一寫
    明確:
    數(shù)據(jù)源
    數(shù)據(jù)的目的地:

  • 創(chuàng)建一個字節(jié)輸入流對象,在構(gòu)造方法中綁定要讀取的數(shù)據(jù)源
  • 創(chuàng)建一個
  • 流對象,構(gòu)造方法中綁定要寫入的目的地
  • 使用字節(jié)輸入流對象中的當(dāng)打中read讀取文件
  • 使用字節(jié)輸出流中的方法write,把讀取到的字節(jié)寫入到目的地文件中
  • 釋放資源
  • public class Copy {public static void main(String[] args) throws IOException {// 1.創(chuàng)建流對象// 1.1 指定數(shù)據(jù)源FileInputStream fis = new FileInputStream("D:\\test.jpg");// 1.2 指定目的地FileOutputStream fos = new FileOutputStream("test_copy.jpg");// 2.讀寫數(shù)據(jù)// 2.1 定義數(shù)組byte[] b = new byte[1024];// 2.2 定義長度int len;// 2.3 循環(huán)讀取while ((len = fis.read(b))!=-1) {// 2.4 寫出數(shù)據(jù)fos.write(b, 0 , len);}// 3.關(guān)閉資源fos.close();fis.close();} }

    字符流

    當(dāng)使用字節(jié)流讀取文本文件時,可能會有一個小問題。就是遇到中文字符時,可能不會顯示完整的字符,那是因為一個中文字符可能占用多個字節(jié)存儲。所以Java提供一些字符流類,以字符為單位讀寫數(shù)據(jù),專門用于處理文本文件。

    GBK:占用兩個字節(jié)
    utf-8:占用三個字節(jié)

    字符輸入流【Reader】

    java.io.Reader抽象類是表示用于讀取字符流的所有類的超類,可以讀取字符信息到內(nèi)存中。它定義了字符輸入流的基本共性功能方法。

    共有成員方法

    • public int read(): 從輸入流讀取一個字符。
    • public int read(char[] cbuf): 從輸入流中讀取多個字符,并將它們存儲到字符數(shù)組 cbuf中 。
    • public void close() :關(guān)閉此流并釋放與此流相關(guān)聯(lián)的任何系統(tǒng)資源。

    FileReader類 文件字符輸入流

    java.io.FileReaderextend InputStreamReader··extendReader類
    是讀取字符文件的便利類。構(gòu)造時使用系統(tǒng)默認(rèn)的字符編碼和默認(rèn)字節(jié)緩沖區(qū)。

    作用:把硬盤中的數(shù)據(jù)以字符的方式讀取到內(nèi)存中

    構(gòu)造方法:

    • FileReader(File file): 創(chuàng)建一個新的 FileReader ,給定要讀取的File對象。
    • FileReader(String fileName): 創(chuàng)建一個新的 FileReader ,給定要讀取的文件的名稱。
      參數(shù):讀取的數(shù)據(jù)源
      String fileName:文件的路徑
      File file:文件
      FileReader構(gòu)造方法中的作用:
      1.創(chuàng)建一個FileReader的對象
      2.會把FileReader對象指向要讀取的文件
      當(dāng)你創(chuàng)建一個流對象時,必須傳入一個文件路徑。類似于FileInputStream 。
  • 字符編碼:字節(jié)與字符的對應(yīng)規(guī)則。Windows系統(tǒng)的中文編碼默認(rèn)是GBK編碼表。

    idea中UTF-8

  • 字節(jié)緩沖區(qū):一個字節(jié)數(shù)組,用來臨時存儲字節(jié)數(shù)據(jù)。

  • 字符輸入流的使用步驟?
    1.創(chuàng)建FileReader對象,構(gòu)造方法中要綁定要讀取的數(shù)據(jù)源
    2.使用FileReader對象中的方法Read讀取文件
    3.釋放資源

    讀取字符數(shù)據(jù)

  • 讀取字符:read方法,每次可以讀取一個字符的數(shù)據(jù),提升為int類型,讀取到文件末尾,返回-1,循環(huán)讀取,代碼使用演示:
  • public class FRRead {public static void main(String[] args) throws IOException {// 使用文件名稱創(chuàng)建流對象FileReader fr = new FileReader("read.txt");// 定義變量,保存數(shù)據(jù)int b ;// 循環(huán)讀取while ((b = fr.read())!=-1) {System.out.println((char)b);}// 關(guān)閉資源fr.close();} } 輸出結(jié)果: 黑 馬 程 序 員

    使用字符數(shù)組讀取:read(char[] cbuf),每次讀取b的長度個字符到數(shù)組中,返回讀取到的有效字符個數(shù),讀取到末尾時,返回-1 ,代碼使用演示:

    String類構(gòu)造方法:
    String(char[] value):把字符數(shù)組轉(zhuǎn)換為字符串
    String(char[] value,int offset ,int count):把字符數(shù)組一部分轉(zhuǎn)換為字符串

    public class FRRead {public static void main(String[] args) throws IOException {// 使用文件名稱創(chuàng)建流對象FileReader fr = new FileReader("read.txt");// 定義變量,保存有效字符個數(shù)int len ;// 定義字符數(shù)組,作為裝字符數(shù)據(jù)的容器char[] cbuf = new char[2];// 循環(huán)讀取while ((len = fr.read(cbuf))!=-1) {System.out.println(new String(cbuf));}// 關(guān)閉資源fr.close();} } 輸出結(jié)果: 黑馬 程序 員序

    獲取有效的字符改進(jìn),代碼使用演示:

    public class FISRead {public static void main(String[] args) throws IOException {// 使用文件名稱創(chuàng)建流對象FileReader fr = new FileReader("read.txt");// 定義變量,保存有效字符個數(shù)int len ;// 定義字符數(shù)組,作為裝字符數(shù)據(jù)的容器char[] cbuf = new char[2];// 循環(huán)讀取while ((len = fr.read(cbuf))!=-1) {System.out.println(new String(cbuf,0,len));}// 關(guān)閉資源fr.close();} }輸出結(jié)果: 黑馬 程序 員

    字符輸出流【W(wǎng)riter】

    java.io.Writer抽象類是表示用于寫出字符流的所有類的超類,將指定的字符信息寫出到目的地。它定義了字節(jié)輸出流的基本共性功能方法。

    • void write(int c) 寫入單個字符。
    • void write(char[] cbuf)寫入字符數(shù)組。
    • abstract void write(char[] cbuf, int off, int len)寫入字符數(shù)組的某一部分,off數(shù)組的開始索引,len寫的字符個數(shù)。
    • void write(String str)寫入字符串。
    • void write(String str, int off, int len) 寫入字符串的某一部分,off字符串的開始索引,len寫的字符個數(shù)。
    • void flush()刷新該流的緩沖。
    • void close() 關(guān)閉此流,但要先刷新它。

    FileWriter類 文件字符輸出流

    作用: 把內(nèi)存中的字符數(shù)數(shù)劇寫入到文件中
    java.io.FileWriterextends OutputStreamWrite extends··Write
    java.io.FileWriter類是寫出字符到文件的便利類。構(gòu)造時使用系統(tǒng)默認(rèn)的字符編碼和默認(rèn)字節(jié)緩沖區(qū)。

    構(gòu)造方法:

    • FileWriter(File file): 創(chuàng)建一個新的 FileWriter,給定要讀取的File對象。
    • FileWriter(String fileName): 創(chuàng)建一個新的 FileWriter,給定要讀取的文件的名稱。

    當(dāng)你創(chuàng)建一個流對象時,必須傳入一個文件路徑,類似于FileOutputStream。

    參數(shù):寫入文件的目的地
    String fileName:文件的路徑
    File file:文件
    構(gòu)造方法中的作用:

  • 會創(chuàng)建一個FileWriter對象
  • 會根據(jù)構(gòu)造方法中傳遞的文件/文件路徑創(chuàng)建文件
  • 會把FileWriter對象指向創(chuàng)建好的文件
  • 字符輸出流的使用步驟:

  • 創(chuàng)建FileWriter對象。構(gòu)造方法中綁定要寫入的數(shù)據(jù)的目的地
  • 使用FileWriter中的方法write,把數(shù)據(jù)寫入到內(nèi)存緩沖區(qū)中(字符轉(zhuǎn)換為字節(jié)的過程)
  • 使用FileWriter中的方法flush,把內(nèi)存緩沖區(qū)中的數(shù)據(jù),刷新到文件中
  • 釋放資源(會先把內(nèi)存緩沖區(qū)中的數(shù)據(jù),刷新到文件中)
  • 基本寫出數(shù)據(jù)

    寫出單個字符:write(int b) 方法,每次可以寫出一個字符數(shù)據(jù),代碼使用演示:

    public class FWWrite {public static void main(String[] args) throws IOException {// 使用文件名稱創(chuàng)建流對象FileWriter fw = new FileWriter("fw.txt"); // 寫出數(shù)據(jù)fw.write(97); // 寫出第1個字符fw.write('b'); // 寫出第2個字符fw.write('C'); // 寫出第3個字符fw.write(30000); // 寫出第4個字符,中文編碼表中30000對應(yīng)一個漢字。/*【注意】關(guān)閉資源時,與FileOutputStream不同。如果不關(guān)閉,數(shù)據(jù)只是保存到緩沖區(qū),并未保存到文件。*/// fw.close();} } 輸出結(jié)果: abC田
  • 雖然參數(shù)為int類型四個字節(jié),但是只會保留一個字符的信息寫出。
  • 未調(diào)用close方法,數(shù)據(jù)只是保存到了緩沖區(qū),并未寫出到文件中。
  • 關(guān)閉和刷新

    因為內(nèi)置緩沖區(qū)的原因,如果不關(guān)閉輸出流,無法寫出字符到文件中。但是關(guān)閉的流對象,是無法繼續(xù)寫出數(shù)據(jù)的。如果我們既想寫出數(shù)據(jù),又想繼續(xù)使用流,就需要flush 方法了。

    • flush :刷新緩沖區(qū),流對象可以繼續(xù)使用。
    • close:先刷新緩沖區(qū),然后通知系統(tǒng)釋放資源。流對象不可以再被使用了。

    寫出其他數(shù)據(jù)

  • 寫出字符數(shù)組 :write(char[] cbuf) 和 write(char[] cbuf, int off, int len) ,每次可以寫出字符數(shù)組中的數(shù)據(jù),用法類似FileOutputStream,代碼使用演示:
  • public class FWWrite {public static void main(String[] args) throws IOException {// 使用文件名稱創(chuàng)建流對象FileWriter fw = new FileWriter("fw.txt"); // 字符串轉(zhuǎn)換為字節(jié)數(shù)組char[] chars = "黑馬程序員".toCharArray();// 寫出字符數(shù)組fw.write(chars); // 黑馬程序員// 寫出從索引2開始,2個字節(jié)。索引2是'程',兩個字節(jié),也就是'程序'。fw.write(b,2,2); // 程序// 關(guān)閉資源fos.close();} }
  • 寫出字符串:write(String str) 和 write(String str, int off, int len) ,每次可以寫出字符串中的數(shù)據(jù),更為方便,代碼使用演示:
  • public class FWWrite {public static void main(String[] args) throws IOException {// 使用文件名稱創(chuàng)建流對象FileWriter fw = new FileWriter("fw.txt"); // 字符串String msg = "黑馬程序員";// 寫出字符數(shù)組fw.write(msg); //黑馬程序員// 寫出從索引2開始,2個字節(jié)。索引2是'程',兩個字節(jié),也就是'程序'。fw.write(msg,2,2); // 程序// 關(guān)閉資源fos.close();} }
  • 續(xù)寫和換行:操作類似于FileOutputStream。
    使用兩個參數(shù)的構(gòu)造方法:
    FileWriter(String fileName,Boolean append)
    FileWriter(File file,Boolean append)
  • Boolean append:
    true:可以續(xù)寫,不回創(chuàng)建新的文件覆蓋源文件
    false:創(chuàng)建新的文件覆蓋源文件

    public class FWWrite {public static void main(String[] args) throws IOException {// 使用文件名稱創(chuàng)建流對象,可以續(xù)寫數(shù)據(jù)FileWriter fw = new FileWriter("fw.txt"true); // 寫出字符串fw.write("黑馬");// 寫出換行fw.write("\r\n");// 寫出字符串fw.write("程序員");// 關(guān)閉資源fw.close();} } 輸出結(jié)果: 黑馬 程序員

    流中的異常處理

    jdk1.7之前使用try...catch...finally處理流中的異常

    public class HandleException1 {public static void main(String[] args) {// 聲明變量,提高變量作用域,聲明時可以沒有值,使用時必須有值FileWriter fw = null;try {//可能會出現(xiàn)異常的代碼創(chuàng)建流對象fw = new FileWriter("fw.txt");// 寫出數(shù)據(jù)fw.write("黑馬程序員"); //黑馬程序員} catch (IOException e) {//異常的處理邏輯e.printStackTrace();} finally {try { //若創(chuàng)建對象失敗,fw默認(rèn)值時null,null不能調(diào)用方法,會拋出nullponitException,需要增加一個判斷不是null,則釋放資源if (fw != null) {fw.close();}} catch (IOException e) {e.printStackTrace();}}} }

    JDK7的新特性:
    在try之后增加一個();
    在括號中可以定義流對象,那么這個流對象的作用域就在try中有效,try中代碼執(zhí)行完畢,會自動把流對象釋放掉,不用寫finally,
    格式如下:

    try (創(chuàng)建流對象語句,如果多個,使用';'隔開) {// 讀寫數(shù)據(jù) } catch (IOException e) {e.printStackTrace(); }

    代碼使用演示:

    public class HandleException2 {public static void main(String[] args) {// 創(chuàng)建流對象try ( FileWriter fw = new FileWriter("fw.txt"); ) {// 寫出數(shù)據(jù)fw.write("黑馬程序員"); //黑馬程序員} catch (IOException e) {e.printStackTrace();}} }

    JDK9的改進(jìn)(擴(kuò)展知識點(diǎn)了解內(nèi)容)

    try的前邊可以定義流對象
    在try后邊()中可以直接引入流對象的名稱(變量名)
    在try代碼執(zhí)行完畢之后流對象也可以釋放掉,不用寫finally

    JDK9中try-with-resource 的改進(jìn),對于引入對象的方式,支持的更加簡潔。被引入的對象,同樣可以自動關(guān)閉,無需手動close,我們來了解一下格式。
    A a =new A();
    B b=new B();
    try(a,b){
    可能會產(chǎn)出異常的代碼,
    } catch(異常類變量 變量名){
    異常的處理邏輯
    }

    public class TryDemo {public static void main(String[] args) throws IOException {// 創(chuàng)建流對象** final ** FileReader fr = new FileReader("in.txt");FileWriter fw = new FileWriter("out.txt");// 引入到try中try (fr; fw) {// 定義變量int b;// 讀取數(shù)據(jù)while ((b = fr.read())!=-1) {// 寫出數(shù)據(jù)fw.write(b);}} catch (IOException e) {e.printStackTrace();}} }

    屬性集

    概述

    java.util.Properties 繼承于Hashtable ,來表示一個持久的屬性集。它使用鍵值結(jié)構(gòu)存儲數(shù)據(jù),每個鍵及其對應(yīng)值都是一個字符串。該類也被許多Java類使用,比如獲取系統(tǒng)屬性時,System.getProperties 方法就是返回一個Properties對象。

    java.util.Properties extends hashtable<K,v>implements Map<K,v>

    Properties類

    表示了一個持久的屬性集Properties可保存在流中或從流中加載。

    Properties集合是唯一一個和IO流相結(jié)合的集合

    可以使用Properties集合中的臨時數(shù)據(jù),持久化寫入到硬盤中存儲、

    可以使用Properties集合中的方法load,把硬盤中保存的文件(鍵值對),讀取到集合中使用

    Properties屬性列表中每個鍵及其對對應(yīng)的值都是一個字符串

    Properties是一個雙列集合,key和value默認(rèn)都是字符串

    構(gòu)造方法

    • public Properties() :創(chuàng)建一個空的屬性列表。

    基本的存儲方法

    使用Properties結(jié)合存儲數(shù)據(jù),遍歷取出Properties集合中的數(shù)據(jù)
    是一個雙列集合,Key和value都是字符串

    • public Object setProperty(String key, String value) : 保存一對屬性。 調(diào)用hashtable的方法put
    • public String getProperty(String key) :使用此屬性列表中指定的鍵搜索屬性值。通過key找到value值,此方法相當(dāng)于map集合中的get(key)方法
    • public Set<String> stringPropertyNames() :所有鍵的名稱的集合。返回此屬性列表中的鍵集,其中該鍵及其對應(yīng)值是字符串,此方法相當(dāng)于Map集合中的KeySet方法
    public class ProDemo {public static void main(String[] args) throws FileNotFoundException {// 創(chuàng)建屬性集對象Properties properties = new Properties();// 添加鍵值對元素properties.setProperty("filename", "a.txt");properties.setProperty("length", "209385038");properties.setProperty("location", "D:\\a.txt");// 打印屬性集對象System.out.println(properties);// 通過鍵,獲取屬性值System.out.println(properties.getProperty("filename"));System.out.println(properties.getProperty("length"));System.out.println(properties.getProperty("location"));// 遍歷屬性集,獲取所有鍵的集合Set<String> strings = properties.stringPropertyNames();// 打印鍵值對for (String key : strings ) {System.out.println(key+" -- "+properties.getProperty(key));}} }輸出結(jié)果: {filename=a.txt, length=209385038, location=D:\a.txt} a.txt 209385038 D:\a.txt filename -- a.txt length -- 209385038 location -- D:\a.txt

    與流相關(guān)的方法

    可以使用properties集合中的方法store,把集合中的臨時數(shù)據(jù),持久化寫入到硬盤中存儲

    void store (OutputStream out,String comments)
    void store(Write write,String comments)
    參數(shù):
    OutputStream out:不可以寫入中文
    Write write:字符輸出流,可以寫入中文
    String comments:注釋,用來解釋說明保存的文件是做什么用的,不能使用中文,會產(chǎn)生亂碼默認(rèn)unicide編碼,一般使用“空字符串”

    使用步驟:

  • 創(chuàng)建Properties 集合對象,添加數(shù)據(jù)
  • 創(chuàng)建字節(jié)輸出流/字符輸出流對象,構(gòu)造方法中綁定要輸出的目的地
  • 使用Properties集合中的方法store,把集合中的臨時數(shù)據(jù),持久化寫入到硬盤中存儲
  • 釋放資源
  • Properties pro = new Properties();創(chuàng)建Properties集合 pro.setProperty(“11”,“11 ”); FileWrite fw=new FileWrite("Filename"); pro.store(fw,"savedate"); fw.close();

    可以使用Properties集合中的方法load,把硬盤中保存的文件(鍵值對),讀取到集合中使用

    • public void load(InputStream inStream): 從字節(jié)輸入流中讀取鍵值對。
    • public void load(Reader reader):

    參數(shù):
    (InputStream inStream):字節(jié)輸入流,不能讀取含有中文的鍵值對,
    Reader reader:字符輸入流,可以讀取含有中文的鍵值對

    通過流對象,可以關(guān)聯(lián)到某文件上,這樣就能夠加載文本中的數(shù)據(jù)了。文本數(shù)據(jù)格式:

    使用步驟:

  • 創(chuàng)建Properties集合對象
  • 使用Properties集合對象中的方法load讀取保存鍵值對文件
  • 遍歷Properties集合
  • 注意:

  • 存儲鍵值對的文件中,鍵與值默認(rèn)的連接符號使用=, 空格(其他符號)
  • 存儲鍵值對的文件中,可使用#進(jìn)行注釋,被注釋的鍵值對不會再被讀取
  • 鍵與值默認(rèn)都是字符串,不用再加引號
  • filename=a.txt length=209385038 location=D:\a.txt

    加載代碼演示:
    一般使用字符流

    public class ProDemo2 {public static void main(String[] args) throws FileNotFoundException {// 創(chuàng)建屬性集對象Properties pro = new Properties();// 加載文本中信息到屬性集pro.load(new FileInputStream("read.txt"));// 遍歷集合并打印Set<String> strings = pro.stringPropertyNames();for (String key : strings ) {System.out.println(key+" -- "+pro.getProperty(key));}} } 輸出結(jié)果: filename -- a.txt length -- 209385038 location -- D:\a.txt

    小貼士:文本中的數(shù)據(jù),必須是鍵值對形式,可以使用空格、等號、冒號等符號分隔。

    緩沖流,也叫高效流,是對4個基本的FileXxx 流的增強(qiáng),所以也是4個流,按照數(shù)據(jù)類型分類:

    緩沖流

    緩沖流的基本原理,是在創(chuàng)建流對象時,會創(chuàng)建一個內(nèi)置的默認(rèn)大小的緩沖區(qū)數(shù)組,通過緩沖區(qū)讀寫,減少系統(tǒng)IO次數(shù),從而提高讀寫的效率。

    字節(jié)緩沖流

    BufferedInputStream,字節(jié)緩沖輸入流

    所有子類共性的方法:

    • public void close() :關(guān)閉此輸入流并釋放與此流相關(guān)聯(lián)的任何系統(tǒng)資源。

    • public abstract int read(): 從輸入流讀取數(shù)據(jù)的下一個字節(jié)。

    • public int read(byte[] b): 從輸入流中讀取一些字節(jié)數(shù),并將它們存儲到字節(jié)數(shù)組 b中 。

    close方法,當(dāng)完成流的操作時,必須調(diào)用此方法,釋放系統(tǒng)資源。

    BufferedOutputStream 字節(jié)緩沖輸出流

    共性方法:

    • public void close() :關(guān)閉此輸出流并釋放與此流相關(guān)聯(lián)的任何系統(tǒng)資源。
    • public void flush() :刷新此輸出流并強(qiáng)制任何緩沖的輸出字節(jié)被寫出。
    • public void write(byte[] b):將 b.length字節(jié)從指定的字節(jié)數(shù)組寫入此輸出流。
    • public void write(byte[] b, int off, int len) :從指定的字節(jié)數(shù)組寫入 len字節(jié),從偏移量 off開始輸出到此輸出流。
    • public abstract void write(int b) :將指定的字節(jié)輸出流。

    close方法,當(dāng)完成流的操作時,必須調(diào)用此方法,釋放系統(tǒng)資源。


    字節(jié)緩沖輸入流

    構(gòu)造方法

    • public BufferedInputStream(InputStream in) :創(chuàng)建一個 新的緩沖輸入流。 ,保存其參數(shù),即輸入流in,以便將來使用
    • public BufferedInputStream(InputStream in,int size ) :創(chuàng)建一個 具有指定緩沖區(qū)大小的緩沖輸入流,并保存其參數(shù)

    參數(shù):
    InputStream in字節(jié)輸入流:我們可以傳遞FileInputStream,增加一個緩沖區(qū),提高FileInputStream的讀取效率
    int size:指定緩沖流內(nèi)部緩沖區(qū)大小,不指定默認(rèn)

    使用步驟
    1.創(chuàng)建FileInputStream對象,構(gòu)造方法中綁定要讀取的數(shù)據(jù)源
    2.創(chuàng)建BufferedInputStream對象,構(gòu)造方法中傳遞FileInputStream對象,提高FileInputStream對象效率
    3.使用BufferedInputStream對象中的方法read ,讀取文件
    4.釋放資源(會調(diào)用Flue方法刷新數(shù)據(jù))


    字節(jié)緩沖輸出流
    • public BufferedOutputStream(OutputStream out): 創(chuàng)建一個新的緩沖輸出流。以將數(shù)據(jù)寫入指定的底層輸出流

    • public BufferedOutputStream(OutputStream out,int size): 創(chuàng)建一個新的緩沖輸出流。以將數(shù)據(jù)寫入指定的底層輸出流

    參數(shù)
    OutputStream out:字節(jié)輸出流
    我們可以傳遞FileOutputStream,緩沖流會給FileOutoutStream增加一個緩沖區(qū),提高FileOutputStream 的寫入效率

    使用步驟
    1.創(chuàng)建FileOutputStream對象,構(gòu)造方法中綁定要輸出目的地
    2.創(chuàng)建BufferedOutputStream對象,構(gòu)造方法中傳遞FileOutputStream對象 對象,提高FileOutputStream對象效率
    3.使用BufferedOutputStream對象中的方法write,把數(shù)據(jù)寫入到內(nèi)部緩沖區(qū),

    4.使用BufferedOutputStream對象中的方法flush把內(nèi)部緩沖區(qū)中的數(shù)據(jù),刷新到文件中
    5.釋放資源(會調(diào)用Flue方法刷新數(shù)據(jù))

    構(gòu)造舉例,代碼如下:

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

    關(guān)閉緩沖流,會自動關(guān)閉基本流

    效率測試

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

    如何更快呢?

    使用數(shù)組的方式,代碼如下:

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

    字符緩沖流

    共性方法

    • void write(int c) 寫入單個字符。
    • void write(char[] cbuf)寫入字符數(shù)組。
    • abstract void write(char[] cbuf, int off, int len)寫入字符數(shù)組的某一部分,off數(shù)組的開始索引,len寫的字符個數(shù)。
    • void write(String str)寫入字符串。
    • void write(String str, int off, int len) 寫入字符串的某一部分,off字符串的開始索引,len寫的字符個數(shù)。
    • void flush()刷新該流的緩沖。
    • void close() 關(guān)閉此流,但要先刷新它。

    BufferedWriter字符緩沖輸出流

    構(gòu)造方法
    BufferedWriter(writer out):創(chuàng)建一個使用默認(rèn)大小輸出緩沖區(qū)的緩沖輸出流

    BufferedWriter(writer out,int sz):創(chuàng)建一個使用給定大小輸出緩沖區(qū)的新緩沖字符輸出流

    參數(shù):
    writer out:字符輸出流
    我們可以傳遞一個FileWriter,緩沖流會給FileWriter增加一個緩沖區(qū),提高FileWrite的寫入效率
    int sz:指定緩沖區(qū)的大小,不寫默認(rèn)大小

    特有成員方法:
    Void newLine():寫入一個分隔符,會根據(jù)不同的操作系統(tǒng),獲取不同的行分隔符
    換行符號:
    windows:\r\n
    linux:/n
    mac:/r

    使用步驟:
    1.創(chuàng)建字符緩沖輸出流對象,構(gòu)造方法中傳遞字符輸出流
    2.調(diào)用字符緩沖流中的方法,write,把數(shù)據(jù)寫入到內(nèi)存緩沖區(qū)中
    3.調(diào)用字符緩沖流中的方法flush,把內(nèi)存緩沖區(qū)中的數(shù)據(jù),刷新到文件中
    4.釋放資源

    BufferedReader,extends Reader 字符緩沖輸入流

    • 共有成員方法
    • public int read(): 從輸入流讀取一個字符。
    • public int read(char[] cbuf): 從輸入流中讀取多個字符,并將它們存儲到字符數(shù)組 cbuf中 。
    • public void close() :關(guān)閉此流并釋放與此流相關(guān)聯(lián)的任何系統(tǒng)資源。

    構(gòu)造方法
    BufferedReader(Reader in):創(chuàng)建一個使用默認(rèn)大小的輸出緩沖的緩沖字符輸入流

    BufferedReader(Reader in,int sz):創(chuàng)建一個使用指定大小的緩沖區(qū)的緩沖字符輸入流
    參數(shù)
    Reader in:字符輸入流我們可以傳遞FileReader,緩沖流會給FileReader增加一個緩沖區(qū),提高FileReader的讀取效率

    int sz:
    特有成員方法
    String readLine():讀取一個文本行 。讀一行數(shù)據(jù),行的終止符號:通過列字符之一即可認(rèn)為某行已終止,換行\(zhòng)n 回車\r,回車后跟著換行(\r\n)
    返回值:包含該行內(nèi)容字符串,不包含任何行終止符,如果已到達(dá)流末尾,則返回null

    使用步驟

  • 創(chuàng)建字符緩沖輸入流對象,構(gòu)造方法中傳遞字符輸入流
  • 使用字符緩沖輸入流對象中的方法read/readline讀取文本
  • 釋放資源
    readLine方法演示,代碼如下:
  • public class BufferedReaderDemo {public static void main(String[] args) throws IOException {// 創(chuàng)建流對象BufferedReader br = new BufferedReader(new FileReader("in.txt"));// 定義字符串,保存讀取的一行文字String line = null;// 循環(huán)讀取,讀取到最后返回nullwhile ((line = br.readLine())!=null) {System.out.print(line);System.out.println("------");}// 釋放資源br.close();} }

    1.4 練習(xí):文本排序

    練習(xí):
    對文本的內(nèi)容進(jìn)行排序

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

    案例分析

    1.創(chuàng)建一個HashMap集合對象,可以存儲每行文本的序號,value存儲每行的文本
    2.創(chuàng)建字符緩沖輸入流對象,構(gòu)造方法綁定字符輸入流
    3.創(chuàng)建字符緩沖輸出流對象,構(gòu)造方法中綁定字符輸出流
    4.使用字符緩沖輸入流的方法readLine,逐行讀取文本
    5.對讀取到的文本 進(jìn)行切割,獲取行中的序號和文本內(nèi)容
    6.把切割好的序號和文本的內(nèi)容存儲到Hashmap集合中(key序號是有序的,會自動排序)
    7.遍歷HashMap集合,獲取每一個鍵值對
    8.把每一個鍵值對拼接為一個文本行
    9.把拼接好的文本,使用字符緩沖輸出流中的方法write,寫入到文件中
    10.釋放資源

    案例實(shí)現(xiàn)

    public class BufferedTest {public static void main(String[] args) throws IOException {//1. 創(chuàng)建map集合,保存文本數(shù)據(jù),鍵為序號,值為文字HashMap<String, String> lineMap = new HashMap<>();// 2.創(chuàng)建字符緩沖輸入流對象,構(gòu)造方法中綁定字符輸入流BufferedReader br = new BufferedReader(new FileReader("in.txt"));//3.創(chuàng)建一個字符緩沖輸出流對象,構(gòu)造方法中綁定字符串輸出流BufferedWriter bw = new BufferedWriter(new FileWriter("out.txt")); //4.使用字符緩沖輸出流中的方法readLine逐行讀取文本// 讀取數(shù)據(jù)String line = null;while ((line = br.readLine())!=null) {// 解析文本String[] split = line.split("\\.");// 保存到集合lineMap.put(split[0],split[1]);}// 釋放資源br.close();// 遍歷map集合for (int i = 1; i <= lineMap.size(); i++) {String key = String.valueOf(i);// 獲取map中文本String value = lineMap.get(key);// 寫出拼接文本bw.write(key+"."+value);// 寫出換行bw.newLine();}// 釋放資源bw.close();} }

    轉(zhuǎn)換流

    字符編碼和字符集

    按照某種規(guī)則,將字符存儲到計算機(jī)中,稱為編碼 。反之,將存儲在計算機(jī)中的二進(jìn)制數(shù)按照某種規(guī)則解析顯示出來,稱為解碼

    字符編碼:就是一套自然語音字符與二進(jìn)制數(shù)之間的對應(yīng)規(guī)則

    字符集:也叫編碼表,是一個系統(tǒng)支持所有字符的集合

    Idea默認(rèn)編碼utf-8

    FileReader可以讀取IO默認(rèn)編碼格式UTF-8的文件
    FileReader讀取系統(tǒng)默認(rèn)編碼GBK中文 會產(chǎn)生亂碼

    InputStreamReader類

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

    構(gòu)造方法

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

    參數(shù):
    InputSrteam in:字節(jié)輸入流,用來讀取文件中保存的字節(jié)
    String charsetName:指定的編碼表名稱,不區(qū)分大小寫,可以實(shí)Utf-8,Gbk。。。。不指定默認(rèn)使用UTF-8

    使用步驟:

  • 創(chuàng)建InputStreamReader對象,構(gòu)造方法重視傳遞字節(jié)輸出流和指定的編碼表名稱。
  • 使用InputStreamReader對象中的方法read讀取文件
  • 釋放資源
  • 注意事項:
    構(gòu)造方法中指定的編碼表民晨光要和文件的編碼相同,否則會發(fā)生亂碼

    OutputStreamWriter類

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

    構(gòu)造方法

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

    參數(shù)
    OutputStream out:字節(jié)輸出流,用來寫轉(zhuǎn)換之后的字節(jié)到文件中
    String charsetName:指定的編碼表名稱,不區(qū)分大小寫,可以是Utf-8,GBK…,不指定默認(rèn)使用Utf-8

    使用步驟

  • 創(chuàng)建OutputStreamWrite對象,構(gòu)造方法中傳遞字節(jié)輸出流和指定編碼表名稱
  • 使用OutputStreamWrite,把字符轉(zhuǎn)換為字節(jié)存儲在緩沖區(qū)中(編碼)
  • 使用OutputStreamWrite對象中的方法flush,把內(nèi)存緩沖區(qū)的字節(jié)刷新到文件中(使用字節(jié)流寫字節(jié)的過程)
  • 釋放資源
  • 指定編碼寫出

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

    練習(xí):轉(zhuǎn)換文件編碼

    將GBK編碼的文本文件,轉(zhuǎn)換為UTF-8編碼的文本文件。

    案例分析

    1.創(chuàng)建InputStreanReader對象,構(gòu)造方法中傳遞字節(jié)輸入流和指定的編碼表名稱GBK
    2.創(chuàng)建OutputStreamWrite對象,構(gòu)造方法中傳遞字節(jié)輸出流和指定的編碼表utf-8
    3.使用InputSteamReader對象中的方法read讀取文件
    4.使用OutputStreamWrite方法write,把讀取的數(shù)據(jù)寫入到文件中
    5.釋放資源

    案例實(shí)現(xiàn)

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

    序列化

    概述

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

    反之,該字節(jié)序列還可以從文件中讀取回來,重構(gòu)對象,對它進(jìn)行反序列化。對象的數(shù)據(jù)、對象的類型和對象中存儲的數(shù)據(jù)信息,都可以用來在內(nèi)存中創(chuàng)建對象。

    把對象以流的方式,寫入到文件中保存,叫寫對象,也可以叫對象的序列化
    對象中包含的不僅僅是字符使用字節(jié)流
    ObjectOutputStream:對象的序列化writeObject(p)

    把文件中保存的對象,以流的方式讀取出來,叫做讀對象,也叫對象的反序列化
    讀取的文件保存的都是字節(jié)使用字節(jié)流
    ObjectInputStream:對象的反序列化流
    readObject()

    ObjectOutputStream類

    作用:把對象以流的方式寫入到文件中保存
    java.io.ObjectOutputStreamextends OutputStream 類,將Java對象的原始數(shù)據(jù)類型寫出到文件,實(shí)現(xiàn)對象的持久存儲。

    構(gòu)造方法

    • public ObjectOutputStream(OutputStream out): 創(chuàng)建一個指定OutputStream的ObjectOutputStream。
      參數(shù):

    OutputStream out:字節(jié)輸出流

    構(gòu)造舉例,代碼如下:

    特有的成員方法:

    • public final void writeObject (Object obj) : 將指定的對象寫出。

    使用步驟,需要序列化對象實(shí)現(xiàn)類
    1.創(chuàng)建ObjectOutputStream對象,構(gòu)造方法中傳遞字節(jié)輸出流
    2.使用ObjectOutputStream對象中的方法writeObject,把對象寫入到文件中
    3.釋放資源

    序列化操作

    1.一個對象要想序列化,必須滿足兩個條件:

    • 該類必須 實(shí)現(xiàn)java.io.Serializable 接口來啟用序列化功能,Serializable 是一個標(biāo)記接口,不實(shí)現(xiàn)此接口的類將不會使任何狀態(tài)序列化或反序列化,會拋出NotSerializableException 。實(shí)現(xiàn)Serializable接口,會給類添加一個標(biāo)記,當(dāng)序列化和反序列化的時候,就會檢測類上是否有這個標(biāo)記

    • 該類的所有屬性必須是可序列化的。如果有一個屬性不需要可序列化的,則該屬性必須注明是瞬態(tài)的,使用transient 關(guān)鍵字修飾。

    • static關(guān)鍵字:靜態(tài)關(guān)鍵字
      靜態(tài)優(yōu)先于非靜態(tài)加載到內(nèi)存中(靜態(tài)優(yōu)先于對象進(jìn)入到內(nèi)存中)被static修飾的成員變量不能被序列化

    • transient 瞬態(tài)關(guān)鍵字: 被其修飾,不能被序列化
    public class Employee implements java.io.Serializable {public String name;public String address;public transient int age; // transient瞬態(tài)修飾成員,不會被序列化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 {// 創(chuàng)建序列化流對象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();}} } 輸出結(jié)果: Serialized data is saved

    ObjectInputStream類

    ObjectInputStream反序列化流,將之前使用ObjectOutputStream序列化的原始數(shù)據(jù)恢復(fù)為對象。
    作用:把文件中保存的對象,以流的方式讀取出來使用

    構(gòu)造方法

    • public ObjectInputStream(InputStream in): 創(chuàng)建一個指定InputStream的ObjectInputStream。
      參數(shù)InputStream in:字節(jié)輸入流

    特有成員方法:

    • public final Object readObject () : 從ObjectInputStream讀取一個對象。

    使用步驟:
    1.創(chuàng)建一個ObjectInputStream對象,構(gòu)造方法中傳遞字節(jié)輸入流
    2.使用ObjectInputStream對象中的方法readObject讀取保存對象的文件
    3.釋放資源
    4.使用讀取出來的對象

    反序列化操作1

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

    • public final Object readObject () : 讀取一個對象。

    readObject方法聲明拋出了ClassNotFoundException(class文件找不到異常)當(dāng)不存在對象的class文件時拋出異常
    反序列化前提:

  • 類必須實(shí)現(xiàn)Serializable
  • 必須存在類對應(yīng)的class文件
  • public class DeserializeDemo {public static void main(String [] args) {Employee e = null;try { // 創(chuàng)建反序列化流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

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

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

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

    問題:
    每次修改類的定義,都會給class文件生成一個新得序列號
    解決方法:
    無論是否對類的定義進(jìn)行修改,都不生成新的序列號
    可以手動給類添加一個序列號
    格式在Serializable 接口規(guī)定:
    可序列化類可以通過聲明為serialVersionUID的字段(該字段必須是static)最終final的long星字段,顯示聲明其自己的serialVersionUID

    static final long serialVersionUID=42L

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

    練習(xí):序列化集合

  • 將存有多個自定義對象的集合序列化操作,保存到list.txt文件中。
  • 反序列化list.txt ,并遍歷集合,打印對象信息。
  • 練習(xí):
    當(dāng)我們想在文件中保存多個對象的時候
    可以把多個對象存儲到一個集合中
    對象進(jìn)行序列化和反序列化

    分析:

  • 定義一個存儲Person對象的Array List集合

  • 往ArrayList集合中存儲Person對象

  • 創(chuàng)建一個序列化流ObjectOutputStream

  • 使用ObjectOutputStream對象中的方法writeObject,對集合進(jìn)行序列化

  • 創(chuàng)建一個反序列化Object InputStream對象

  • 使用ObjectInputStream對象中的方法readObject讀取文件中保存的集合

  • 把Object類型的集合轉(zhuǎn)換為ArraysList類型

  • 遍歷ArrayList集合

  • 釋放資源

  • 案例分析

  • 把若干學(xué)生對象 ,保存到集合中。
  • 把集合序列化。
  • 反序列化讀取時,只需要讀取一次,轉(zhuǎn)換為集合類型。
  • 遍歷集合,可以打印所有的學(xué)生信息
  • 案例實(shí)現(xiàn)

    public class SerTest {public static void main(String[] args) throws Exception {// 創(chuàng)建 學(xué)生對象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"));// 讀取對象,強(qiáng)轉(zhuǎn)為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 {// 創(chuàng)建 序列化流 ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("list.txt"));// 寫出對象oos.writeObject(arrayList);// 釋放資源oos.close();} }

    打印流

    概述

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

    PrintStream類extends OutputStream

    為其他輸出流添加了功能,是他們能夠方便的打印各種數(shù)據(jù)值表示形式

    特點(diǎn):

  • 只負(fù)責(zé)數(shù)據(jù)的輸出,不負(fù)責(zé)數(shù)據(jù)的讀取
  • 與其他輸出流不同,其永遠(yuǎn)不回拋出IOexception
  • 特有方法:print,println可以輸出任意類型的值
  • 構(gòu)造方法

    • public PrintStream(String fileName): 使用指定的文件名創(chuàng)建一個新的打印流。輸出目的地是一個文件路徑

    • public PrintStream(File file): 使用指定的文件創(chuàng)建一個新的打印流。輸出目的地是一個文件

    • public PrintStream(Output Stream): 使用指定的輸出流創(chuàng)建一個新的打印流。輸出目的地是一個字節(jié)輸出流

    構(gòu)造舉例,代碼如下:

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

    繼承自父類的成員方法

    • public void close() :關(guān)閉此輸出流并釋放與此流相關(guān)聯(lián)的任何系統(tǒng)資源。
    • public void flush() :刷新此輸出流并強(qiáng)制任何緩沖的輸出字節(jié)被寫出。
    • public void write(byte[] b):將 b.length字節(jié)從指定的字節(jié)數(shù)組寫入此輸出流。
    • public void write(byte[] b, int off, int len) :從指定的字節(jié)數(shù)組寫入 len字節(jié),從偏移量 off開始輸出到此輸出流。
    • public abstract void write(int b) :將指定的字節(jié)輸出流。

    注意事項
    如果使用繼承自父類的write方法寫數(shù)據(jù),那么查看數(shù)據(jù)的時候會查詢編碼表
    如果使用自己特有的print/println方法寫數(shù)據(jù),寫的數(shù)據(jù)會原樣輸出

    使用步驟

  • 創(chuàng)建打印流PrintStream對象,構(gòu)造方法中綁定要輸出的目的地(會拋出文件找不到異常,不回拋出IO異常)
  • 使用父類方法或自己特有方法
  • 釋放資源
  • 改變打印流向

    System.out就是PrintStream類型的,只不過它的流向是系統(tǒng)規(guī)定的,打印在控制臺上。

    可以改變輸出語句的目的地(打印流的流向)
    輸出語句,默認(rèn)在控制臺輸出
    使用System.setOut方法改變輸出語句的目的地改為參數(shù)傳遞的打印流的目的地
    static void setOut(PrintStream out )
    重新分配“標(biāo)準(zhǔn)”輸出流

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

    總結(jié)

    以上是生活随笔為你收集整理的Java笔记整理六(File类,递归,字节流IO,字符流IO,流中的异常处理,属性集Properties,缓冲流,转换流,序列化,打印流)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。