java-IO輸入輸出流

一.java.io.File類

  • java.io.File類用于表示文件/目錄
  • File只用于表示文件的信息(名稱,大小等),不能用于文件內(nèi)容的訪問
  • RandomAccessFile java提供的對文件內(nèi)容的訪問(可以對文件進(jìn)行讀寫),可以訪問文件的任意位置
  • 代碼位置

java文件模型
在硬盤上的文件是byte btye btye存儲的,是數(shù)據(jù)的集合

二.RandomAccessFile 類對于文件的讀寫

  • 打開文件
    有兩種模式 "rw"(讀寫) "r"(只讀)
    RandomAccessFile raf = new RandomeAccessFile(file,"rw");
     文件指針,打開文件時指針在開頭 pointer = 0;
  • 寫方法
    raf.write(int) 只寫一個字節(jié)(后8位) ,同時指針指向下一個位置,準(zhǔn)備再次寫入
  • 讀取文件
    int b = raf.read(); 只讀一個字節(jié)
  • 文件讀寫后一定要關(guān)閉raf.close()
  • 代碼位置

IO流(輸入流,輸出流)

三.字節(jié)流

  • InputStream 抽象了應(yīng)用程序讀取數(shù)據(jù)的方式
  • OutputStream 抽象了應(yīng)用程序?qū)懗鰯?shù)據(jù)的方式
  • EOF = End 讀到-1就到文件結(jié)尾
  • 輸入流基本方法
    int b = in.read();讀取一個字節(jié)無符號填充到int的低八位,前面補(bǔ)0, -1是EOF
    in.read(byte[] buf) 讀取數(shù)據(jù)填充到字節(jié)數(shù)組buf中
    in.read(byte[] buf, int start, int size) 從輸入流的start開始位置存放size長度的數(shù)據(jù)到buf數(shù)組中;
  • 輸出流的基本方法
    out.write(int b) 寫出一個byte到流,b的低八位
    out.write(byte[] buf) 將buf字節(jié)數(shù)組寫入到流
    out.write(btye[], int start ,int size) 字節(jié)數(shù)組buf從start開始位置寫size長度的字節(jié)到流
  • FileInputStream 具體實現(xiàn)了在文件上讀取數(shù)據(jù)


    Paste_Image.png
  • FileOutputStream 實現(xiàn)了向文件中寫出byte數(shù)據(jù)的方法
  • 代碼位置

四.對流功能的擴(kuò)展,可以更加方便的讀取int,long,z字符等類型的數(shù)據(jù);

其實方式只是封裝了FileInputStream和FileOutputStream的write和read方法,
注意寫入文件的內(nèi)容還是字節(jié)碼
比如:DataOutputStream.writeInt() 實現(xiàn)方式調(diào)用FileOutputStream.write()四次寫入四個字節(jié)而已

  • DataOutputStream 寫出數(shù)據(jù)
    /**
     * 對流功能的擴(kuò)展寫出數(shù)據(jù)(DataOutputStream)
     * @throws IOException 
     */
    public static void dataOut(File file) throws IOException
    {
        DataOutputStream out = new DataOutputStream(new FileOutputStream(file));
        //寫入一個整型10
        out.writeInt(10);
        //寫入一個整型20
        out.writeInt(20);
        //寫入一個長整型10
        out.writeLong(10l);
        //寫入一個布爾true
        out.writeBoolean(true);
        //寫入一個雙浮點
        out.writeDouble(10.5);
        //寫入一個UTF-8編碼的字符
        out.writeUTF("中國我愛你");
        out.close();
    }
  • DataInputStream 讀取數(shù)據(jù)
   /**
    * 對流功能的擴(kuò)展讀取數(shù)據(jù)(DataInputStream)
    * 注意寫入文件的內(nèi)容還是字節(jié)碼
    * @throws IOException 
    */
   public static void dataInput(File file) throws IOException
   {
       DataInputStream in = new DataInputStream(new FileInputStream(file));
       //讀取一個整形數(shù)據(jù)
       int int1 = in.readInt();
       //讀取一個整形數(shù)據(jù)
       int int2 = in.readInt();
       //讀取一個長整型數(shù)據(jù)
       long int3 = in.readLong();
       //讀取一個boolean數(shù)據(jù)
       boolean b = in.readBoolean();
       //讀取一個Double類型數(shù)據(jù)
       Double d = in.readDouble();
       //讀取一個utf8編碼的數(shù)據(jù)
       String str1 = in.readUTF();
       //以下數(shù)據(jù)結(jié)果:10, 20, 10, true, 10.5, 中國我愛你
       System.out.println(int1 + ", " + int2 + ", "  + int3 + ", " +  b + ", " + d + ", "  +  str1);   
       in.close();
   }

測試:

File file = new File("/home/lxf/test/test.php");
IOUtil.dataOut(file);
IOUtil.dataInput(file);//輸出:10, 20, 10, true, 10.5, 中國我愛你

五.字節(jié)流緩沖

BufferedInputStream & BufferedOutputStream
這兩個字節(jié)流未IO提供了帶緩沖區(qū)的操作,一般打開文件進(jìn)行寫入或讀取操作時候,都會加上緩沖,這種模式提高了IO的性能;
從應(yīng)用程序中把輸入放入文件,相當(dāng)于將一缸水導(dǎo)入另一個缸中;

  • FileOutputStream.write()方法相當(dāng)與一滴一滴的把水"轉(zhuǎn)移"過去
  • DataOutputStream.writeXxx()方法會方便一些,一瓢一瓢的把水"轉(zhuǎn)移"
  • BufferedOutStream.write()方法更方便一些,先將水,一瓢一瓢的放入桶中,然后在從桶中"轉(zhuǎn)移"到另一個容器中;
  • 三種方式copy文件,速度比較:字節(jié)批量讀取 > 帶緩沖方式 > 單個字節(jié)方式
 FileIutputStream.read(buf,0,buf.length) >  BufferedOutStream.read() > FileIutputStream.read()

五.字符流

  • java中的文本(char) : 是16位的無符號整數(shù),是字符的unicode編碼( 雙字節(jié)編碼 )

  • 文件: 是byte byte btye....的數(shù)據(jù)序列

  • 文本文件是文本(char)序列按著某種編碼方案(UTF-8, UTF-16be,gbk等)序列化為byte的存儲結(jié)果

  • 兩個抽象類(Reader, Writer)操作的是文本文件;

  • 字符的處理是一次處理一個字符

  • 字符的底層仍然是基本的字節(jié)序列

  • 兩個實現(xiàn)類
    InputStreamReader 完成byte流解析為char流, 按著編碼解析

          //原文件讀取
          FileInputStream in = new FileInputStream(srcFile);
          InputStreamReader isr = new InputStreamReader(in, "utf-8");
    

    OutStreamWriter 提供char流到byte流, 按著編碼處理

          //目標(biāo)文件寫入
          FileOutputStream out = new FileOutputStream(destFile);
          OutputStreamWriter osw = new OutputStreamWriter(out,"utf-8");
    
  • FileReader 和 FileWriter 兩個類以對文件直接讀寫

       FileReader  reader = new FileReader(srcFile);
       FileWriter writer = new FileWriter(destFile);

五.字符流的過濾器

  • BufferedReader 一次讀一行
        //對文件進(jìn)行讀取操作
        FileInputStream in = new FileInputStream(srcFile);
        InputStreamReader isr = new InputStreamReader(in, "utf-8");
        //FileReader  isr = new FileReader(srcFile);
        BufferedReader br = new BufferedReader(isr);
  • BufferedWriter/PrintWriter 一次寫一行
        //對文件進(jìn)行寫入操作
        FileOutputStream out = new FileOutputStream(destFile);
        OutputStreamWriter isr1 = new OutputStreamWriter(out, "utf-8");
        BufferedWriter bw = new BufferedWriter(isr1);

  PrintWriter pw = new PrintWriter(destFile);

六.序列化的基本操作

  • 對象的序列化 : 就是將Object轉(zhuǎn)換成byte序列, 反之叫對象的反序列化;
  • 序列化流 ( ObjectOutputStream )
  • 反序列化流 ( ObjectInputStream )
  • 序列化接口 ( Serializable )
    對象必須實現(xiàn)序列化接口,才能進(jìn)行序列化
  • 代碼位置

七. transient關(guān)鍵字

  • transient 關(guān)鍵字標(biāo)識的實體類屬性不會進(jìn)行jvm的默認(rèn)序列化
  • 也可以自己完成該元素的序列化
/**
 * Students學(xué)生實體類, 實現(xiàn)了Serializable接口,可以被序列化
 * @author lxf
 *
 */
public class Students implements Serializable {
    private int id;
    private String uname;
    //transient關(guān)鍵字,表明pass屬性不會進(jìn)行jvm的默認(rèn)序列化, 也可以自己完成該元素的序列化
    private transient String pass;
    
    /*
     * 自己完成被transient關(guān)鍵字修飾的屬性序列化
     */
    private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException
    {
        //把jvm能默認(rèn)序列化的元素進(jìn)行序列化操作
        s.defaultWriteObject();
        //自己完成pass的序列化
        s.writeObject(pass);
    }   
    /*
     * 自己完成被transient關(guān)鍵字修飾的屬性反序列化
     */
    private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException
    {
        s.defaultReadObject();
        this.pass = (String) s.readObject();
    }

八.序列化中子類和父類構(gòu)造函數(shù)的調(diào)用問題

  • 一個類實現(xiàn)了序列化接口,那么其子類都可以進(jìn)行序列化
  • 對于類對象進(jìn)行反序列化操作時,如果其父類沒有實現(xiàn)序列化接口,而子類自己實現(xiàn)了序列化接口,那么其父類的構(gòu)造函數(shù)會被調(diào)用,
  • 對于類對象進(jìn)行反序列化操作時,如果其父類實現(xiàn)序列化接口,二子類沒有實現(xiàn)了序列化接口,那么其父類的構(gòu)造函數(shù)不會被調(diào)用,
class Foo {
    public Foo(){
        System.out.println("Foo...");
    }
}
class Foo1 extends Foo implements Serializable{
    public Foo1(){
        System.out.println("Foo1...");
    }
}
class Foo2 extends Foo1 implements Serializable{
    public Foo2(){
        System.out.println("Foo2...");
    }
}
        File file = new File("/home/lxf/test/Foo2");
        Foo2 f = new Foo2();
        /*
         * 將Foo2對象序列化存儲到/home/lxf/test/Foo2
         * 控制臺依次輸出:
         * Foo...
            Foo1...
            Foo2...
         */
        SerializeDemo.ObjSaveToFile(file, f);
        /*
         * 將/home/lxf/test/Foo2中的序列化后的內(nèi)容反序列化讀出為對象
         * 控制臺依次輸出:
         * Foo...
            com.lxf.IOStream.Foo2@732768bb
            說明: 
            對于類對象進(jìn)行反序列化操作時,如果其父類沒有實現(xiàn)序列化接口,而子類自己實現(xiàn)了序列化接口,那么其父類的構(gòu)造函數(shù)會被調(diào)用
            對于類對象進(jìn)行反序列化操作時,如果其父類實現(xiàn)序列化接口,而子類沒有實現(xiàn)了序列化接口,那么其父類的構(gòu)造函數(shù)不會被調(diào)用
         */
        SerializeDemo.seriFileToObj(file);
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容