Java(9-1)輸入與輸出(一)

我們將會介紹如何在JAVA中進行輸入和輸出操作。

part 1 大體介紹輸入輸出流
在JavaAPI中,可以從其中讀入一個字節序列的對象稱作輸入流,而可以向其中寫入一個字節序列的對象稱爲輸出流。這些字節序列的來源和目的地可以是文件,也可以是網絡連接,甚至內存塊。**抽象類!**InputStream 和 OutputStream 構成了輸入和輸出各類層次的基礎。

part 2.1 讀寫字節虛類的介紹
在InputStream中有許多很有用的抽象方法,其中有一些可能會在子類中重寫,例如:
read()方法。這個方法將讀入一個字節,並返回讀入的字節,或者在遇到輸入源結尾時返回-1。在我們具體的輸入流類中,他往往被重寫以提供適用的功能。

與之類似OutputStream類中也定義了類似的方法——abstract void write(int b)

read和write方法在執行時都將阻塞,直至字節確實被讀入或寫出。

available方法可以讓我們去檢查當前可讀入的字節數量,那我們就可以通過這個方法來避免,read和write沒有可讀信息的阻塞:

int by = in.available();
if(by > 0)
{
    byte[] data = new byte[byteAvailable];
    in.read(data);
}

當我們完成了對輸入/輸出流的讀寫時,應該通過他們的close方法來關閉它,這可以及時釋放我們有限的系統資源。
我們可以使用衆多繼承InputStream和OutputStream的類,而不是直接使用字節

Tip:我們的讀寫都是按照一個字節進行的,但是Unicode編碼有兩個字節,所以我們對Unicode文本建立了Reader和Writer的抽象類,基本方法與InputStream和OutputStream類似。

part 2.2 輸入/輸出流過濾器的組合

FileInputStream和FileOutputStream可以提供磁盤上文件的輸入流和輸出流,而你只需要提供文件民或者文件的完整路徑即可。但是注意,他們是抽象類InputStream和OutputStream類一樣,是基於一個字節操作的。

FileInputStream fin = new FileInputStream("emplotee.dat");

上面那行代碼可以查看用戶目錄下的名爲employee.dat的文件。(我們當然可以絕對路徑)

我們以後會看到,DataInputStram,只能讀入數值類型。

而FileInpuStream沒有任何讀入數值類型的方法,DataInputStream也沒有任何從文件中獲取數據的方法。

在Java中,我們使用一種機制來融合分離這兩種職責,簡單說,這過程感覺像是過濾一樣,我們可以這樣:

FileInputStram fin = new FileInputStream("emplotee.dat");
DataInputStream din = new DataInputStream(fin);
double x = din.readDouble();

我們可以通過嵌套過濾器來添加多重功能過濾來獲得數據。例如,輸入流在默認情況下是不被緩衝區緩存的,相比之下,請求一個數據塊並將其置於緩衝區會顯得更加高效。如果我們想使用緩衝機制,以及用於文件的數據輸入方法,那麼就需要使用下面這種構造序列:

DataInputStream din = new DataInputStream(
    new BufferedInputStream(
        new FileInputStream("employee.dat")));

part 2.3 如何寫出文本輸出
對於文本輸出,我們用PrintWriter。這個類擁有以文本格式打印字符串和數字的方法,它還有一個將PrinterWriter鏈接到FileWriter的便捷方法:

PrintWriter out = new PrintWriter("employee.txt","UTF-8");

等同於:

PrintWriter out = new PrintWriter(new FileOutputStream("employee.txt"),"UTF-8");

爲了打印寫出器,需要使用System.out的print, println, printf方法,例如:

//上面有outout.print();

part 2.4 如何讀入文本輸入

最簡單的處理任意文本的方式就是我們常見的Scanner類。
我們可以將短小的文本文件,像這樣讀入到這樣的一個字符串:

String content = new String(Files.readALLbYTES(path),charset);

如果我們想將這個文件一行行地讀入,那我們可以這樣:

List<String> lines = Files.readAllLines(path, charset);

如果文件太大,那麼可以將行惰性處理爲一個Stream< String >對象:

try(Stream< String >lines = Files.lines(path, charset))
{
    ...
}

part 2.3 以文本格式存儲對象

package TextFileTest;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.Scanner;

public class TextTest {
    public static void main(String[] args) throws IOException {
        Employee[] staff = new Employee[3];
        // 創建數組內容
        staff[0] = new Employee("黃一東",10000);
        staff[1] = new Employee("黃瑋東",20000);
        staff[2] = new Employee("黃瑋琛",30000);

        // 寫出通過寫出類來 寫出staff的內容 。 這裏的PrintWriter自己內部會實現FileOutputStream
        try(PrintWriter out = new PrintWriter("Employee.dat","UTF-8"))
        {
            // 調用WriteData 先向文本寫入數組的大小,再根據數組大小分別調用WriteEmpolyee
            // 按照格式寫入各個數據
            writeData(staff, out);
        } 

        // 通過讀入類 Scanner來讀入employee.dat(UTF-8)的內容  這裏顯式的調用了
        // FileInputStream類 組合了流類 
        try(Scanner in = new Scanner(new FileInputStream("employee.dat"),"UTF-8"))
        {
            // 這裏調用readData(文件讀入流對象) 先獲取文件第一行保存的對象行數(n),然後再跳到下一行
            // 調用readEmployee每次讀取一行內容 循環n次 每次保存內容到數組newStaff中
            Employee[] newStaff = readData(in);

            for(Employee e:newStaff)
                System.out.println(e);
        }
    }

    private static void writeData(Employee[] employees, PrintWriter out)throws IOException{
        out.println(employees.length);

        for(Employee e:employees)
            writeEmployee(out, e);
    }

    public static void writeEmployee(PrintWriter out, Employee e){
        out.println(e.getName() + "|" + e.getSalary());
    }

    private static Employee[] readData(Scanner in){
        // 得到數組大小
        int n = in.nextInt();
        in.nextLine();

        Employee[] employees = new Employee[n];
        for(int i = 0; i < n; i++)
        {
            employees[i] = readEmployee(in);
        }
        return employees;
    }

    public static Employee readEmployee(Scanner in){
        String line = in.nextLine();
        String[] tokens = line.split("\\|");
        String name = tokens[0];
        int salary = Integer.parseInt(tokens[1]);
        return new Employee(name, salary);
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章