1. 程式人生 > >IO流學習總結(一)

IO流學習總結(一)

什麼是IO流IO流之前也接觸了好多次,因為這一塊內容很多,所以老是有不太清楚的地方,所以現在來總結一下。流分為位元組流,字元流。簡單的說,位元組流就是由二進位制資料組成的流,一個位元組八個bit,這個計算機很容易理解,但是不方便人閱讀,所以就有了字元流。字元流,有不同的編碼方式。IO流中類很多,但是層次關係還是很明顯的,畫圖比較能說明問題
InputStream用於位元組序列的讀取
OutputStream用於位元組序列的寫入
Reader和Writer是面向字元的流,他們處理的物件是字串
簡單說一下,因為這些後面都會總結,這些其實只是繼承關係的一部分,其實主要用到的就是FileXXXStream,BufferedXXXStream,DataXXXStream。這裡的FiliterInputStream使用了裝飾者模式,用於對InputStream子類的擴充套件。什麼是裝飾者模式?
簡單的來說,裝飾者模式由抽象物件,抽象構件,裝飾抽象物件,裝飾構件組成他們的關係像是這樣
裝飾物件是對抽象物件的擴充套件,我們知道一個良好的類意味著減少自己內部例項和方法被修改的可能,同時也要增加擴充套件的機會。在此基礎上,如果要增加擴充套件,有繼承和組合兩種辦法,但是繼承會增加類之間的耦合性,不利於進一步擴充套件。因此使用組合的裝飾者模式,是不錯的選擇。
上下的兩幅圖多像啊,IO流中的Filiter就是使用了裝飾者模式對抽象流進行了擴充套件這裡,推薦一個部落格,雖然他裡面沒有更具體的例子,但是這種直接構建裝飾器的方式更容易遷移到IO流的理解上接來下,先從簡單的字元流總結字元流文字編碼只需知道UTF-8和UTF-16屬於Unicode標準的編碼就好了,而現在一般都用unicode編碼位元組流轉換為字元流
使用InputStreamReader或OutputStreamWriter可以將位元組流轉換為字元流例如從標準輸入中獲得字元流,但是標準輸入本身是一個位元組流Reader in = new InputStreamReader(System.in);字元輸入字元輸入分文標準輸入和文字輸入標準輸入就用上面那個就可以了,或者用Scanner。Scanner s = new Scanner(System.in);文字輸入文字輸入分為傳統Reader和Files.readXXX獲取Files.readXXX
  • 對於短小的文字檔案可以使用下面這個方法:
String content=new String(Files.readAllBytes(path),charset);
  • 如果要將文字一行行的讀入:
List<String> lines=Files.readAllLines(path,charset);
  • 如果檔案很大,那麼可以使用流Stream來處理,Stream的特點之一就是惰性處理,讀到哪算哪那種
try(Stream<String> lines = Files.lines(path,charset)){}(這種叫做try-with-resource方式,對於實現了Closeable的類都可以使用這種方式來自動關閉對資源的佔用)傳統Reader通常使用BufferReader+FileReader的組合來讀取文字或者使用BufferReader+InputStreamReader+InputStream(通常是FileInputStream)字元輸出標準輸出System.out,System.err這個應該沒什麼好說的文字輸出通常使用PrintWriter,這個類擁有以文字格式列印字串和數字的方法(BufferReader可沒有處理數字的能力,但是Scanner有處理數字的能力)它還有一個將PrintWriter連結到FileWriter的便捷方法例如:PrintWriter out = new PrintWriter("path","UTF-8");//或者你也可以不指定編碼等同於PrintWriter out = new PrintWriter(new FileOutputStream("path"),"UTF-8");和PrintWriter out = new PrintWriter(new FileWriter("path")));接下來有個例子,可以更具體體會字元輸入輸出:package core.java.IO;import java.io.BufferedReader;import java.io.FileOutputStream;import java.io.FileReader;import java.io.FileWriter;import java.io.IOException;import java.io.PrintWriter;public class ReadAndWriteChar { public static class Employee{ public String name; public int age; public String date; public Employee(String name, int age, String date) { super(); this.name = name; this.age = age; this.date = date; } @Override public String toString() { // TODO Auto-generated method stub return name+" "+age+" "+date; } } private static void writeData(Employee[] employees,PrintWriter out) { int len=employees.length; out.println(len); for (Employee employee : employees) { writeEmployee(employee, out); } } private static void writeEmployee(Employee employee,PrintWriter out) { out.println(employee.name+"|"+employee.age+"|"+employee.date); } private static Employee[] readData(BufferedReader in) throws NumberFormatException, IOException { int len=Integer.parseInt(in.readLine()); Employee[] employees=new Employee[len]; for(int i=0;i<len;i++) { employees[i]=readEmployee(in); } return employees; } private static Employee readEmployee(BufferedReader in) { String[] employeeInfo = null; try { employeeInfo = in.readLine().split("\\|"); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return new Employee(employeeInfo[0], Integer.parseInt(employeeInfo[1]), employeeInfo[2]); } public static void main(String[] args) throws IOException { Employee[] employees= {new Employee("小鐘", 20, "1998-2-3"),new Employee("小齊", 22, "1996-3-32")}; try(PrintWriter pw=new PrintWriter(new FileWriter("E:\\Desktop\\data1\\target.txt"))){ writeData(employees, pw); } Employee[] receive; try(BufferedReader in=new BufferedReader(new FileReader("E:\\Desktop\\data1\\target.txt"))){ receive=readData(in); } for (Employee employee : receive) { System.out.println(employee); } }}輸出:小鐘 20 1998-2-3小齊 22 1996-3-32二進位制資料的讀取
再看下這幅圖,實際上用的多的是BufferedXXXStream,DataXXXStream,FileXXXStream.先從DataXXXStream 總結這是可以將二進位制流轉換為Chars,byte,int,short,long,float,double,char,boolean,utf這些基本資料型別,其中字串以UTF進行編碼例如你要讀取某個檔案DataInputStream in = new DataInputStream(new FileInputSream(path));in.readXXX;寫入檔案DataOutputStream out = new DataOutputStream(new FileOutputStream(path));BufferedInputStream 是裝飾流,用於開啟一個緩衝區進行讀寫,這樣比頻繁地開啟檔案來讀寫要進行的快些,就好像我們的檔案像一口大缸裡的水,如果你每次都是開啟檔案來讀寫那就像每次舀水都要開啟大缸沉重的蓋子,而如果你用緩衝區來處理,就像給這口缸加了一個水龍頭,你每一次讀取就像開啟水龍頭取水一樣輕鬆。BufferedInputStream in=new BufferedInputStream(new FileInputStream("fllename"));