Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> JAVA基礎再回首(二十三)——操作基本數據類型的流、內存操作流、打印流、隨機訪問流、合並流、序列化流

JAVA基礎再回首(二十三)——操作基本數據類型的流、內存操作流、打印流、隨機訪問流、合並流、序列化流

編輯:關於Android編程

有些日子沒寫博客了,當然這段時間也比較忙,大家見諒,好了,話不多說,開始學習吧。

我們繼續學習IO流,還有幾個知識點沒有學。

操作基本數據類型的流

操作基本數據類型

DataInputStream DataOutputStream

操作基本數據類型的流可以讀寫基本數據類型的數據,我們來寫一個簡單的讀寫例子

public class DataStreamDemo {
    public static void main(String[] args) throws IOException {
        // 寫
         write();

        // 讀
        read();
    }

    private static void read() throws IOException {
        // DataInputStream(InputStream in)
        // 創建數據輸入流對象
        DataInputStream dis = new DataInputStream(new FileInputStream("dos.txt"));

        // 讀數據
        byte b = dis.readByte();
        short s = dis.readShort();
        int i = dis.readInt();
        long l = dis.readLong();
        float f = dis.readFloat();
        double d = dis.readDouble();
        char c = dis.readChar();
        boolean bb = dis.readBoolean();

        // 釋放資源
        dis.close();

        System.out.println(b);
        System.out.println(s);
        System.out.println(i);
        System.out.println(l);
        System.out.println(f);
        System.out.println(d);
        System.out.println(c);
        System.out.println(bb);
    }

    private static void write() throws IOException {
        // DataOutputStream(OutputStream out)
        // 創建數據輸出流對象
        DataOutputStream dos = new DataOutputStream(new FileOutputStream("dos.txt"));

        // 寫數據
        dos.writeByte(10);
        dos.writeShort(100);
        dos.writeInt(1000);
        dos.writeLong(10000);
        dos.writeFloat(12.34F);
        dos.writeDouble(12.56);
        dos.writeChar('a');
        dos.writeBoolean(true);

        // 釋放資源
        dos.close();
    }
}

我們先寫數據,然後再讀數據。可以看到讀寫基本數據類型的數據都是ok的。

內存操作流

 


操作字節數組
ByteArrayInputStream ByteArrayOutputStream 操作字符數組
CharArrayReader CharArrayWrite 操作字符串
StringReader StringWriter

 

內存操作流一般用於處理臨時信息,因為臨時信息不需要保存,使用後就可以刪除。
public class ByteArrayStreamDemo {
    public static void main(String[] args) throws IOException {
        // 寫數據 --字節數組輸出流
        ByteArrayOutputStream baos = new ByteArrayOutputStream();

        // 寫數據
        for (int x = 0; x < 10; x++) {
            baos.write(("hello" + x).getBytes());
        }

        // 釋放資源
        // 通過查看源碼我們知道這裡什麼都沒做,所以根本需要close()
        // baos.close();

        // public byte[] toByteArray()
        byte[] bys = baos.toByteArray();

        // 讀數據
        // ByteArrayInputStream(byte[] buf)
        ByteArrayInputStream bais = new ByteArrayInputStream(bys);

        int by = 0;
        while ((by = bais.read()) != -1) {
            System.out.print((char) by);
        }

        // bais.close();
    }
}

上面我們寫英文字符數據可以運用字節數組的輸出流ByteArrayOutputStream,如果我們寫入中文數據的話就要用操作字符數組的流CharArrayWrite了。那麼,剩下的操作字符數組和操作字符串的例子就不做演示了,大家可以自己練練。

打印流

打印流分為兩類

字節流打印流 PrintStream 字符打印流 PrintWriter

打印流的特點:

只有寫數據的,沒有讀取數據。只能操作目的地,不能操作數據源。 可以操作任意類型的數據。 如果啟動了自動刷新,能夠自動刷新。 該流是可以直接操作文本文件的。

我們來回憶一下哪些流對象是可以直接操作文本文件的呢?

 


FileInputStream FileOutputStream FileReader FileWriter PrintStream PrintWriter 看API,查流對象的構造方法,如果同時有File類型和String類型的參數,一般來說就是可以直接操作文件的。
這裡寫圖片描述

 <喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxibG9ja3F1b3RlPg0KCTxwPrTy06HB97XEzNi149PQ0rvM9crHv8nS1LLZ1/fIztLiwODQzbXEyv2+3aOsv8nKx87Sw8e/tLe9t6ijrMv7tcR3cml0Zbe9t6iyu7/J0tTQtGJvb2xlYW7A4NDNtcSjrMv50tTO0sPHvs3Ipb+0v7TL+7XEYXBpo6y/tNPQyrLDtNDCt723qKOstbHIu8rH09C1xKOsztLDx77N1rG908C00afPsMv7tcTQwre9t6iwyaGjPGJyIC8+DQoJPGJyIC8+DQoJv8nS1LLZ1/fIztLiwODQzbXEyv2+3aGj09DBvdbWt723qKOsy/vDx77NyrLDtMf4sfDE2KO/PC9wPg0KCXByaW50KCkgsru74bu70NCjrLK7u+HX1Lavy6LQwsr9vt2hoyBwcmludGxuKCkgsru99r3219S2r8ui0MLBy8r9vt2jrLu5yrXP1sHLyv2+3bXEu7vQ0KGjDQoJPHA+Jm5ic3A7PC9wPg0KPC9ibG9ja3F1b3RlPg0KPHByZSBjbGFzcz0="brush:java;"> public class PrintWriterDemo { public static void main(String[] args) throws IOException { // 創建打印流對象 PrintWriter pw = new PrintWriter("pw2.txt"); pw.print(true); pw.print(100); pw.print("hello"); pw.close(); } } public class PrintWriterDemo { public static void main(String[] args) throws IOException { // 創建打印流對象 PrintWriter pw = new PrintWriter(new FileWriter("pw2.txt"), true); pw.println("hello"); pw.println(true); pw.println(100); pw.close(); } }

分別運行上面的兩個demo,你就會很明顯的看出我們上面總結的區別了。
因此我們還可以總結:
println()方法,其實等價於: bw.write(); bw.newLine(); bw.flush();三個方法

我們用打印流來復制一個文件,我們先來分析

需求:1.txt復制到Copy.txt中(首先你要確認有1.txt,並有內容) 數據源:1.txt – 讀取數據 –> FileReader –高效,所以用–> BufferedReader 目的地:Copy.txt – 寫出數據 –> FileWriter –> BufferedWriter –> PrintWriter
public class CopyFileDemo {
    public static void main(String[] args) throws IOException {
    // 封裝數據源
        BufferedReader br = new BufferedReader(new FileReader(
                "DataStreamDemo.java"));
        // 封裝目的地
        PrintWriter pw = new PrintWriter(new FileWriter("Copy.java"), true);

        String line = null;
        while((line=br.readLine())!=null){
            pw.println(line);
        }

        pw.close();
        br.close();
    }
}

這樣比以前的那種寫法簡單多了吧,什麼,以前的那種寫法你別告訴我你又忘記了,那好吧,我來給你寫寫吧

        // 以前的版本
        // 封裝數據源
        BufferedReader br = new BufferedReader(new FileReader("1.txt"));
        //封裝目的地

        BufferedWriter bw = new BufferedWriter(new FileWriter("Copy.txt"));

         String line = null;
         while ((line = br.readLine()) != null) {
         bw.write(line);
         bw.newLine();
         bw.flush();

好了,這下get到了吧。

隨機訪問流

RandomAccessFile

概述:RandomAccessFile類不屬於流,是Object類的子類。但它融合了InputStream和OutputStream的功能。支持對隨機訪問文件的讀取和寫入。

這個類我以前寫視頻斷點上傳的時候就用到了,很強大的一個類,我們下面來學習下。

public RandomAccessFile(String name,String mode):
第一個參數是文件路徑,第二個參數是操作文件的模式。
模式有四種,我們最常用的一種叫”rw”,這種方式表示我既可以寫數據,也可以讀取數據
下面我們就用這個類來寫一個簡單的讀寫操作的例子

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

         // 創建隨機訪問流對象
        RandomAccessFile raf = new RandomAccessFile("raf.txt", "rw");

        // 寫入數據
        raf.writeInt(100);
        raf.writeChar('a');
        raf.writeUTF("中國");

        raf.close();
    }

}

運行程序,然後我們繼續來寫讀的方法

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

         // 創建隨機訪問流對象
        RandomAccessFile raf = new RandomAccessFile("raf.txt", "rw");

        int i = raf.readInt();
        System.out.println(i);
        // 該文件指針可以通過 getFilePointer方法讀取,並通過 seek 方法設置。
        System.out.println("當前文件的指針位置是:" + raf.getFilePointer());

        char ch = raf.readChar();
        System.out.println(ch);
        System.out.println("當前文件的指針位置是:" + raf.getFilePointer());

        String s = raf.readUTF();
        System.out.println(s);
        System.out.println("當前文件的指針位置是:" + raf.getFilePointer());

        // 我就要讀取a,怎麼辦呢?
        raf.seek(4);
        ch = raf.readChar();
        System.out.println(ch);
    }

}

這是隨機訪問流的簡單操作,後面我有空會把之前項目中做過的斷點上傳一個文件,用到了這個類,做一總結。

合並流

SequenceInputStream

概述:SequenceInputStream類可以將多個輸入流串流在一起,合並為一個輸入流,因此,該流也被稱為合並流。

SequenceInputStream的構造方法
SequenceInputStream(InputStream s1, InputStream s2) SequenceInputStream(Enumeration < ? extends InputStream> e) 把多個文件的內容寫入到一個文本文件

以前我們只是將一個文件的內容復制到另外一個文件中,現在這個合並流可以實現將兩個及多個文件的內容復制到一個文件中了,我們來實現以下吧

// 需求:把ByteArrayStreamDemo.java和DataStreamDemo.java的內容復制到Copy.java中

public class SequenceInputStreamDemo {
    public static void main(String[] args) throws IOException {
        InputStream s1 = new FileInputStream("ByteArrayStreamDemo.java");
        InputStream s2 = new FileInputStream("DataStreamDemo.java");
        SequenceInputStream sis = new SequenceInputStream(s1, s2);
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("Copy.java"));

        // 讀寫操作
        byte[] bys = new byte[1024];
        int len = 0;
        while ((len = sis.read(bys)) != -1) {
            bos.write(bys, 0, len);
        }

        bos.close();
        sis.close();
    }
}

運行程序你會在Copy.java文件中看到ByteArrayStreamDemo.java和DataStreamDemo.java文件的內容都復制到了Copy.java文件中。

那麼怎麼合並3個或者三個以上的文件操作呢?

// 需求:把下面的三個文件的內容(ByteArrayStreamDemo.java,CopyFileDemo.java,DataStreamDemo.java)復制到Copy.java中

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

        // SequenceInputStream(Enumeration e)
        // 通過簡單的回顧我們知道了Enumeration是Vector中的一個方法的返回值類型。
        // Enumeration elements()
        Vector v = new Vector();
        InputStream s1 = new FileInputStream("ByteArrayStreamDemo.java");
        InputStream s2 = new FileInputStream("CopyFileDemo.java");
        InputStream s3 = new FileInputStream("DataStreamDemo.java");
        v.add(s1);
        v.add(s2);
        v.add(s3);
        Enumeration en = v.elements();
        SequenceInputStream sis = new SequenceInputStream(en);
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("Copy.java"));

        // 如何寫讀寫呢,其實很簡單,你就按照以前怎麼讀寫,現在還是怎麼讀寫
        byte[] bys = new byte[1024];
        int len = 0;
        while ((len = sis.read(bys)) != -1) {
            bos.write(bys, 0, len);
        }

        bos.close();
        sis.close();
    }
}

運行程序,我們會在Copy.java文件中看到那三個文件的內容,我們要是想合並四個或者以上的文件,只需要繼續將文件創建輸入流對象然後添加在Vector集合中就可以實現了。

序列化流

序列化流
ObjectOutputStream 反序列化流
ObjectInputStream

序列化流:把對象按照流一樣的方式存入文本文件或者在網絡中傳輸。對象 –> 流數據(ObjectOutputStream)

反序列化流:把文本文件中的流對象數據或者網絡中的流對象數據還原成對象。流數據 –>對象(ObjectInputStream)

//我們先寫一個實體類,並實現序列化接口
public class Person implements Serializable {

    private String name;

    private int age;

    public Person() {
        super();
    }

    public Person(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }

    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;
    }

    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + "]";
    }
}

//寫入數據
public class ObjectStreamDemo {
    public static void main(String[] args) throws IOException{
        // 創建序列化流對象
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("oos.txt"));

        // 創建對象
        Person p = new Person("阿杜", 25);

        // public final void writeObject(Object obj)
        oos.writeObject(p);

        // 釋放資源
        oos.close();
    }
}
//讀取數據
public class ObjectStreamDemo {
    public static void main(String[] args) throws IOException, ClassNotFoundException{
        // 創建反序列化對象
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(
                "oos.txt"));

        // 還原對象
        Object obj = ois.readObject();

        // 釋放資源
        ois.close();

        // 輸出對象
        System.out.println(obj);
    }
}

輸出結果:Person [name=阿杜, age=25]

我們也可以這樣理解

對象序列化是將對象狀態轉換為可保持或傳輸的過程。一般的格式是與平台無關的二進制流,可以將這種二進制流持久保存在磁盤上,也可以通過網絡將這種二進制流傳輸到另一個網絡結點。
對象反序列化,是指把這種二進制流數據還原成對象。

好了,IO流我們就學到這裡了。大家沒事了多練習練習。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved