天天看點

java-IO流相關知識

引言

在上一篇中提到了IO流中的位元組流和字元流的相關概念,那麼,在這個部分,主要說明其它相關IO流的知識。

LineNumberReader類:

跟蹤行号的緩沖字元輸入流,此類定義了方法 setLineNumber(int) 和 getLineNumber(),它們可分别用于設定和擷取目前行号。

String readLine():讀取一行

做一個簡單的案例進行了解:

案例:讀取檔案,每次讀取一行列印并且加上行号

package com.stu_02;
import java.io.FileReader;
import java.io.IOException;
import java.io.LineNumberReader;
/*
   案例:讀取檔案,每次讀取一行列印并且加上行号
 */
public class LineNumberReaderStu {
    public static void main(String[] args) throws IOException {
        //建立跟蹤行号的字元緩沖輸入流
        LineNumberReader lnr = new LineNumberReader(new FileReader("prop1.txt"));
        // public void setLineNumber(int lineNumber):設定起始行号
        lnr.setLineNumber();
        String line;
        //周遊
        while ((line=lnr.readLine())!=null) {
            //擷取行号和内容
            System.out.println(lnr.getLineNumber()+" "+line);
        }
        //關流
        lnr.close();
    }
}
           

編譯運作結果如下:

11 #Sat May 13 16:41:42 CST 2017

12 zhangsan=10

13 lisi=100

14 wangwu=4

操作基本資料類型的流

可以操作基本類型的流對象。

DataInputStream:讀資料

DataOutputStream:寫資料

注意:

讀寫順序必須一緻,否則資料有問題。

記憶體操作流:

解決臨時資料存儲的問題。

操作位元組數組

ByteArrayInputStream

ByteArrayOutputStream

byte[] toByteArray() 将之前寫入記憶體的流轉換成位元組數組

操作字元數組

CharArrayReader

CharArrayWrite

操作字元串

StringReader

StringWriter

将資料寫到流中儲存在記憶體,并且讀取,在這裡,用一個操作字元數組做一解釋說明:

package com.stu_04;
import java.io.CharArrayReader;
import java.io.CharArrayWriter;
import java.io.IOException;
/*
 * 操作字元數組
     CharArrayReader
     CharArrayWrite
 */
public class CharArrayReaderStu {
    public static void main(String[] args) throws IOException {
        //給記憶體中寫資料
        CharArrayWriter caw = new CharArrayWriter();
        caw.write();
        //将記憶體中的資料讀出來
        char[] ch=caw.toCharArray();
        int len;
        CharArrayReader car = new CharArrayReader(ch);
        while ((len=car.read())!=-) {
            System.out.println((char)len);
        }
        //關流
        caw.close();
        car.close();
    }
}
           

編譯運作結果如下:

c

列印流

位元組列印流 PrintStream

字元列印流 PrintWriter

特點:

A:隻能操作目的地,不能操作資料源

B:可以操作任意類型的資料

C:如果啟動了自動重新整理,能夠自動重新整理

D:可以操作檔案的流

注意:什麼流可以直接操作檔案?

看流對象的API,如果其構造方法同時有File和String類型的參數,就可以直接操作檔案。

如何啟動自動重新整理:利用構造

PrintWriter(OutputStream out, boolean autoFlush)

PrintWriter(Writer out, boolean autoFlush)

注意:如果啟動了自動重新整理,就要使用println、printf 或 format的時候,才可以實作自動重新整理

啟動自動重新整理可以實作三個功能:1.寫資料 2.換行 3.重新整理

同樣的,用一個簡單的案例來了解:

利用字元流給檔案中寫資料(int類型,boolean類型),啟動自動重新整理

package com.stu_05;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
//利用字元流給檔案中寫資料(int類型,boolean類型),啟動自動重新整理
public class PrintWriterStu02 {
    public static void main(String[] args) throws IOException { 
        //建立列印字元流對象
        PrintWriter pw = new PrintWriter(new FileWriter("c.txt"),true);
        //寫資料(寫資料、換行、重新整理)
        pw.println();
        pw.println(false);
        //關流
        pw.close(); 
    }
}
           

編譯運作後會在命名為c.txt的文本文檔下看到如下内容:

20

false

标準輸入輸出流

System類下有這樣的兩個成員變量:

标準輸入流:

public static final InputStream in

标準輸出流:

public static final PrintStream out

合并流

SequenceInputStream類可以将多個輸入流串流在一起,合并為一個輸入流,是以,該流也被稱為合并流。

構造:

SequenceInputStream(InputStream s1, InputStream s2) :将s1和s2合并成一個輸入流,先讀取s1後讀取s2

利用該方法可以将兩個java檔案合并為一個java檔案

對象的序列化和反序列化

序列化流:把對象按照流一樣的方式寫到檔案或者在網絡中傳輸。

反序列化流:把檔案或者網絡中的流對象資料還原對象。

ObjectOutputStream:序列化流

writeObject(Object obj) 将指定的對象寫入 ObjectOutputStream。

ObjectInputStream:反序列化流

Object readObject() 從 ObjectInputStream 讀取對象。

注意:如果一個類不是實作Serializable接口無法把執行個體化,會報異常java.io.NotSerializableException

類通過實作 java.io.Serializable 接口以啟用其序列化功能。未實作此接口的類将無法使其任何狀态序列化或反序列化。

如何實作序列化?

讓對象所屬類的實作序列化接口。

舉一個簡單的例子來證明上面所說:

//建立學生對象
package com.stu_07;
import java.io.Serializable;
public class Student implements Serializable{
    private String name;
    private int 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 "Student [name=" + name + ", age=" + age + "]";
    }
    public Student(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }
    public Student() {
        super();
        // TODO Auto-generated constructor stub
    }
}
//序列化流
package com.stu_07;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
public class ObjectOutputStreamStu {
    public static void main(String[] args) throws  IOException {
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("oos.txt"));
        Student s = new Student("薛之謙", );
        //将對象寫入序列化流中
        oos.writeObject(s);
        //關流
        oos.close();    
    }
}
//反序列化流
package com.stu_07;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
public class ObjectInputStreamStu {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("oos.txt"));
        Object object = ois.readObject();
        System.out.println(object);
        ois.close();
        }       
    }
           

編譯運作後在oos.txt中會出現如下内容:

java-IO流相關知識

運作後在控制台輸出入下:

Student [name=薛之謙, age=35]

Properties(檢視api實作map接口本質是一個map集合)

Properties:Properties 類表示了一個持久的屬性集。屬性清單中每個鍵及其對應值都是一個字元串。

特點:Properties 可儲存在流中或從流中加載。

Properties的特有功能:

A:添加元素

public Object setProperty(String key,String value)

B:擷取元素

public String getProperty(String key)

public Set stringPropertyNames()

可以和IO流進行結合使用:

把檔案中的資料加載到集合中。注意:檔案中的資料必須是鍵值對象形式的(例如:張傑=謝娜)。

public void load(InputStream inStream): 從輸入流中讀取屬性清單(鍵和元素對)。

public void load(Reader reader):按簡單的面向行的格式從輸入字元流中讀取屬性清單(鍵和元素對)。

把集合中的資料存儲到文本檔案中,并且是按照鍵值對形式存儲的。

public void store(OutputStream out,String comments): 以适合使用 load(InputStream) 方法加載到 Properties 表中的格式,将此 Properties 表中的屬性清單(鍵和元素對)寫入輸出流。

public void store(Writer writer,String comments): 以适合使用 load(Reader) 方法的格式,将此 Properties 表中的屬性清單(鍵和元素對)寫入輸出字元。

結合上面所述,做一個簡單的案例進行了解:

我有一個猜數字小遊戲的程式,請寫一個程式實作在測試類中隻能用5次,超過5次提示:遊戲試玩已結束,請付費

//猜數字代碼
package com.stu_09;
import java.util.Scanner;
public class GuessNumber {
    public static void playGame(){
        int ran=(int) (Math.random()*+);
        Scanner sc=new Scanner(System.in);
        while(true){
            System.out.println("請輸入你猜的數字:");
            int number =sc.nextInt();
            if(number<ran){
                System.out.println("猜小了,請重新輸入:");
            }else if(number>ran){
                System.out.println("猜大了,請重新輸入:");
            }else if(number==ran){
                System.out.println("恭喜你,猜對了!");
                break;
            }
        }
    }
}
//測試代碼
package com.stu_09;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Properties;
/*
 *我有一個猜數字小遊戲的程式,請寫一個程式實作在測試類中隻能用5次,
      超過5次提示:遊戲試玩已結束,請付費
 */
public class Test {
    public static void main(String[] args) throws IOException {
        Properties prop = new Properties();
        //将檔案中的資料加載到集合中
        prop.load(new FileReader("count.txt"));
        //用指定的鍵在屬性清單中搜尋屬性。
        String string = prop.getProperty("count");
        //轉換成int類型
        int number=Integer.parseInt(string);
        //進行判斷
        if(number>){
            System.out.println("次數已到5次,請付費");
        }else{
            GuessNumber.playGame();
            number++;
            //将改變後的鍵值對重新存儲到集合中去
            prop.setProperty("count", number+"");
            //将改變後的鍵值對存儲到檔案中
            prop.store(new FileWriter("count.txt"),null);   
        }   
    }
}
           

每一次玩一次遊戲周,我們可以在count.txt中看到鍵值對的變化,如下:

第一次:

java-IO流相關知識

第二次:

java-IO流相關知識

第三次:

java-IO流相關知識

第四次:

java-IO流相關知識

第五次:

java-IO流相關知識

當猜完五次之後,第六次運作,在控制台會輸出:

次數已到5次,請付費