天天看點

Io流中的其他流資料輸入輸出流記憶體操作流列印流PrintWriter實作自動重新整理和換行标準輸入輸出流二種方式實作鍵盤錄入輸出語句用字元緩沖流改進序列化流和反序列化流

資料輸入輸出流

資料輸入流: DataInputStream

資料輸出流: DataOutputStream

資料輸入輸出流的概述

資料輸入流,讓應用程式讀取原始java資料類型從底層輸入流中的一個獨立于機器的方式。一個應用程式使用一個資料輸出流來寫資料,以後可以通過資料輸入流讀取。

輸入流是不一定安全的多線程通路。線程安全是可選的,是在這個類中的方法的使用者的責任。

特點: 可以寫基本資料類型,可以讀取基本資料類型

資料輸入輸出流的使用

寫基本資料類型

dos.writeInt(45) ;

dos.writeChar('中');

dos.writeUTF("你好");

讀取資料
int a = dis.readInt() ;
System.out.println(a);

char ch = dis.readChar() ;
System.out.println(ch);

String str = dis.readUTF() ;
System.out.println(str);           

示範

public class MyTest {
public static void main(String[] args) throws IOException {
    // 資料輸入輸出流:特點就是能夠讀寫基本資料類型
    // writeData();
    //注意讀取的順序,剛才怎麼寫的,就怎麼讀
    DataInputStream in = new DataInputStream(new FileInputStream("a.txt"));
    boolean b = in.readBoolean();
    double v = in.readDouble();
    int i = in.readInt();
    char c = in.readChar();
    String s = in.readUTF();
    System.out.println(b);
    System.out.println(v);
    System.out.println(c);
    System.out.println(s);

    in.close();

    return;

}

private static void writeData() throws IOException {
    // 資料輸入輸出流:特點就是能夠讀寫基本資料類型
    DataOutputStream out = new DataOutputStream(new FileOutputStream("a.txt"));
    out.writeBoolean(true);
    out.writeDouble(3.14);
    out.writeInt(1000);
    out.writeChar('a');
    out.writeUTF("薛曉燕");
    out.flush();
    out.close();
}           

}

ByteArrayOutputStream out = new ByteArrayOutputStream();

out.write("今天是個好日子".getBytes());

out.write("今天我要嫁給你了".getBytes());

//取出他緩存中的資料

byte[] bytes = out.toByteArray();

String s = new String(bytes);

System.out.println(s);

String s2 = out.toString();

out.close();//此流無需關閉

記憶體操作流

操作位元組數組

ByteArrayInputStream

ByteArrayOutputStream

此流關閉無效,是以無需關閉

操作字元數組

CharArrayWrite
    CharArrayReader           

public class MyTest4 {

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

//操作字元數組

//CharArrayWrite

//CharArrayReader

CharArrayWriter charArrayWriter =new CharArrayWriter();
    charArrayWriter.write("abcd");
    charArrayWriter.write(new char[]{'我','愛','你'});
    char[] chars = charArrayWriter.toCharArray();
    String s1 = new String(chars);
    String s2 = String.valueOf(chars);
    System.out.println(s1);
    System.out.println(s2);

    String s = charArrayWriter.toString();
    System.out.println(s);

}           

操作字元串

StringWriter
    StringReader               

public class MyTest5 {

public static void main(String[] args) {

//操作字元串

// StringWriter

//StringReader

StringWriter stringWriter = new StringWriter();

stringWriter.write("abc");

stringWriter.write("呵呵呵呵呵");

String s = stringWriter.toString();

}           

記憶體操作流的概述

一個 ByteArrayInputStream包含一個内部緩沖區包含的位元組,可以從流中讀取。一個内部計數器跟蹤下一個位元組是由 read提供的方法。

關閉ByteArrayInputStream沒有影響。這個類中的方法可以在流一直沒有産生一個IOException閉叫.

構造方法: public ByteArrayOutputStream()

列印流

列印流的特點

a: 列印流隻能操作目的地,不能操作資料源(不能進行讀取資料)
- b: 可以操作任意資料類型的資料 調用print() 方法可以寫任意資料類型           
  • c: 如果我們啟用自動重新整理,那麼在調用println、printf 或 format 方法中的一個方法的時候,會完成自動重新整理

    /**

    通過以下構造建立對象 能夠啟動自動重新整理 然後調用println、printf 或 format 方法中的一個方法的時候,會完成自動重新整理

    • public PrintWriter(OutputStream out, boolean autoFlush) 啟動 自動重新整理
    • public PrintWriter(Writer out, boolean autoFlush) 啟動自動重新整理

      */

  • d: 這個流可以直接對檔案進行操作(可以直接操作檔案的流: 就是構造方法的參數可以傳遞檔案或者檔案路徑)

    public class MyTest {

    //列印流:隻是寫,不操作源檔案 就是單個的一個流,隻用來輸出

    //位元組列印流 PrintStream

    //字元列印流 PrintWriter

    PrintStream out2 = System.out; //他關聯的裝置是螢幕

    out2.println("abc");

    //這種方式關聯的是檔案
    PrintStream stream = new PrintStream(new File("c.txt"));
    
    stream.println("abc");
    stream.println("abc");
    stream.println("abc");
    stream.println("abc");
    stream.println("abc");
    stream.println("abc");
    stream.println("abc");
    stream.println("abc");
    stream.println("abc");
    stream.write("welcome".getBytes());
    
    stream.close();           

PrintWriter實作自動重新整理和換行

PrintWriter pw = new PrintWriter(new FileWriter("printWriter2.txt") , true) ;

pw.println(true) ;

pw.println(100) ;

pw.println("中國") ;

如果啟用了自動重新整理,則隻有在調用 println、printf 或 format 的其中一個方法時才可能完成此操作

//PrintWriter(OutputStream out, boolean autoFlush)

//通過現有的 OutputStream 建立新的 PrintWriter。

PrintWriter pw = new PrintWriter(new FileOutputStream("cc.txt"), true);

// pw.write("abc");

// 如果啟用了自動重新整理,則隻有在調用 println、printf 或 format 的其中一個方法時才可能完成此操作

pw.println("abc");

pw.flush();

pw.close();

}           

标準輸入輸出流

标準輸入輸出流概述

在System這個類中存在兩個靜态的成員變量:           
  • public static final InputStream in: 标準輸入流, 對應的裝置是鍵盤
  • public static final PrintStream out: 标準輸出流 , 對應的裝置就是顯示器

    System.in的類型是InputStream.

    System.out的類型是PrintStream是OutputStream的孫子類FilterOutputStream 的子類.

    二種方式實作鍵盤錄入

    1.Scanner

    2.BufferedReader的readLine方法。

    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

    //鍵盤錄入的第二種方式

    //Scanner sc = new Scanner(System.in);

    BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));

    while (true){

    System.out.println("請輸入字元串");

    String s = reader.readLine();

    //自定義一個結束标記

    if("886".equals(s)){

    break;

    輸出語句用字元緩沖流改進

  • 擷取System下的in成員變量

    InputStream in = System.in ;

  • in是一個位元組輸入流對象,那麼我們就可以通過這個位元組輸入流對象進行讀取鍵盤錄入的資料.
  • 那麼我們既然要讀取資料,之前我們講解了兩種讀取資料的方式:
    1. 一次讀取一個位元組
    1. 一次讀取一個位元組數組
  • 那麼我們在這個地方使用那種讀取方式. 經過分析,這兩種讀取方式都不太合适.因為資料是客戶通過鍵盤錄入
  • 進來的,而我們希望直接讀取一行資料. 而既然要讀取一行資料,那麼我們就需要使用readLine方法,而這個方法
  • 是屬于BufferedReader的方法,而我們就需要建立一個BufferedReader對象進行讀取資料.而我們這in有屬于
  • 位元組流,而建立BufferedReader對象的時候需要一個字元流,而我們就需要将這個位元組流轉換成字元流,那麼既然
  • 要對其進行轉換,那麼就需要使用轉換流. 需要使用InputStreamReader

    随機通路流

    随機通路流概述

    RandomAccessFile概述 最大特點 能讀能寫

    RandomAccessFile類不屬于流,是Object類的子類。但它融合了InputStream和OutputStream的功能。

    支援對随機通路檔案的讀取和寫入。

    RandomAccessFile的父類是Object , 這個流對象可以用來讀取資料也可以用來寫資料.可以操作任意資料類型的資料.

    我們可以通過getFilePointer方法擷取檔案指針,并且可以通過seek方法設定檔案指針

    序列化流和反序列化流

    序列化流的概述

    所謂的序列化:就是把對象通過流的方式存儲到檔案中.注意:此對象 要重寫Serializable 接口才能被序列化

    反序列化:就是把檔案中存儲的對象以流的方式還原成對象

    序列化流: ObjectOutputStream

    反序列化流: ObjectInputStream

    像這樣一個接口中如果沒有方法,那麼這樣的接口我們将其稱之為标記接口(用來給類打标記的,相當于豬肉身上蓋個章)

    一個對象可以被序列化的前提是這個對象對應的類必須實作Serializable接口

    public class MyTest6 {

    public static void main(String[] args) throws Exception{

    ObjectInputStream stream = new ObjectInputStream(new FileInputStream("list.txt"));

    Object obj = stream.readObject();

    ArrayList<Student> list= (ArrayList<Student>) obj;

    Student student = list.get(2);

    System.out.println(student.getName()+"=="+student.getAge());

    class Student implements Serializable {

    private static final long serialVersionUID = 5760262756605700379L;

    //生成一個類的唯一id

    private String name;

    //transient 修飾成員變量後,此成員變量的就不會序列化到檔案中

    //transient private int age;

    private int age;

    public Student() {

    public Student(String name, int age) {

    this.name = name;

    this.age = age;

    public String getName() {

    return name;

    public void setName(String name) {

    public int getAge() {

    return age;

    public void setAge(int age) {

    如何解決序列化時候的×××警告線問題

    • 我們的一個類可以被序列化的前提是需要這個類實作Serializable接口,就需要給這個類添加一個标記.
    • 在完成序列化以後,序列化檔案中還存在一個标記,然後在進行反序列化的時候,

      會驗證這個标記和序列化前的标記是否一緻,如果一緻就正常進行反序列化,如果

    • 不一緻就報錯了. 而現在我們把這個類做了修改,将相當于更改了标記,而導緻這兩個标記不一緻,就報錯了.
    • 解決問題: 隻要讓這個兩個标記一緻,就不會報錯了吧
    • 怎麼讓這兩個标記一緻呢? 不用擔心,很簡單,難道你們沒有看見×××警告線嗎? ctrl + 1 , 生成出來

      如何讓對象的成員變量不被序列化

      使用transient關鍵字聲明不需要序列化的成員變量
    private transient int age ;// 可以阻止成員變量的序列化使用transient

    Properties的概述

    的 Properties類代表一個持久的特性。的 Properties可以儲存到流或流中加載。屬性清單中的每個鍵和它的相應值是一個字元串。

    屬性清單可以包含另一個屬性清單作為它的“預設”;如果在原始屬性清單中沒有找到屬性鍵,則搜尋該第二個屬性清單。

    • Properties 類表示了一個持久的屬性集。
    • Properties 可儲存在流中或從流中加載。
    • 屬性清單中每個鍵及其對應值都是一個字元串。
    • Properties父類是Hashtable
    • 屬于雙列集合,這個集合中的鍵和值都是字元串 Properties不能指定泛型

      Properties的特殊功能使用

      Properties的load()和store()功能

    • public void load(Reader reader): 讀取鍵值對資料把資料存儲到Properties中
  • public void store(Writer writer, String comments)把Properties集合中的鍵值對資料寫入到檔案中, comments注釋