Java學習總結之第十二章 Java I/O系統

來源:互聯網
上載者:User
一、基本使用總結

1. read方法是阻塞方法,也就是如果流對象中無資料可以讀取時,則read方法會阻止程式繼續向下運行,一直到有資料可以讀取為止。

2. 由於‘\’是Java語言中的特殊字元,所以在代碼內部書寫檔案路徑時,例如代表“c:\test\java\Hello.java”時,需要書寫成“c:\\test\\java\\Hello.java”或“c:/test/java/Hello.java”,這些都需要在代碼中注意。

3. File類中包含了大部分和檔案操作的功能方法,該類的對象可以代表一個具體的檔案或檔案夾。

4. 常見的位元組輸入資料流:

輸入資料流

描述

ByteArrayInputStream

把位元組數群組轉換為輸入資料流

FileInputStream

從檔案中讀取資料

StringBufferInputStream

把字串轉換為輸入資料流。這個類已被廢棄,取而代之的是StringBufferReader

PipedInputStream

串連一個PipedOutputStream

SequenceInputStream

把幾個輸入資料流轉換為一個輸入資料流

ObjectInputStream

對象輸入資料流

FilterInputStream

裝飾器,具有擴充其他輸入資料流的功能

5. 常見的位元組輸出資料流:

輸出資料流

描述

ByteArrayOutputStream

向位元組數組(即記憶體的緩衝區)中寫資料

FileOutputStream

向檔案中寫資料

PipedOutputStream

向管道中輸出資料,與PipedInputStream搭配使用

ObjectOutputStream

對象輸出資料流

FilterOutputStream

裝飾器,擴充其他輸出資料流的功能

6. 在Java平台中,有以下兩種方式能獲得本地平台的字元編碼類型:

a) System.getProperty(“file.encoding”);

b) Charset cs = Charset.defaultCharset(); 註:Charset類位於java.nio.charset包中。

7. Reader類能夠將輸入資料流中採用其他編碼類別型的字元轉換為Unicode字元,然後在記憶體中為這些Unicode字元分配記憶體。Writer類能夠把記憶體中的Unicode字元轉換為其他編碼類別型的字元,再寫到輸出資料流中。預設情況下,Reader和Writer會在本地平台和字元編碼和Unicode字元編碼之間進行轉換,:

如果要輸入或輸出採用特定類型編碼的字串,可以使用InputStreamReader類和OutputStreamWriter類,在它們的構造方法中可以指定輸入資料流或輸出資料流的字元編碼。下示:

8. 常見的Reader類:

Reader類型

描述

CharArrayReader

適配器,把字元數群組轉換為Reader,從字元數組中讀取字元

BufferedReader

裝飾器,為其他Reader提供讀緩衝區,此外,它的readLine()方法能夠讀入一行字串

LineNumberReader

裝飾器,為其他Reader提供讀緩衝區,並且可以跟蹤字串輸入資料流中的符號

StringReader

適配器,把字串轉換為Reader,從字串中讀取字元

PipedReader

串連一個PipedWriter

FilterReader

裝飾器,擴充其他Reader的功能

PushBackReader

裝飾器,能夠把讀到的一個字元壓回到緩衝區中。通常用做編譯器的掃描器,在程式中一般很少使用它

InputStreamReader

適配器,把InputStream轉換為Reader,可以指定資料來源的字元編碼

FileReader

從檔案中讀取字元

9. 常見的Writer類:

Writer類型

描述

CharArrayWriter

適配器,把字元數群組轉換為Writer,向字元數組中寫字元

BufferedWriter

裝飾器,為其他Writer提供寫緩衝區

StringWriter

適配器,把StringBuffer轉換為Writer,向StringBuffer中寫字元

PipedWriter

串連一個PipedReader

FilterWriter

裝飾器,擴充其他Writer的功能

PrintWriter

裝飾器,輸出格式化資料

OutputStreamWriter

適配器,把OutputStream轉換為Writer,可以指定資料來源的字元編碼

FileWriter

向檔案中寫字元

二、裝飾流的使用

1. 比較常用的裝飾流有DataInputStream/DataOutputStream和BufferedReader/BufferedWriter。裝飾流不可以單獨使用,必須本命實體流或裝飾流進行使用。

2. 只有使用DataOutputStream流格式寫入的資料,才可以使用DataInputStream進行讀取,以下是DataOutputStream/DataInputStream的使用執行個體:

//將一定格式的資料寫入test.my檔案中。

//MyData.java

/**

* 類比要儲存到檔案中的資料

* 該類中儲存4種類型的資料

*/

public class MyData {

boolean b;

int n;

String s;

short sh[];

public MyData(){}

public MyData(boolean b,int n,String s,short sh[]){

this.b = b;

this.n = n;

this.s = s;

this.sh = sh;

}

}

//WriteFileUseDataStream.java

import java.io.DataOutputStream;

import java.io.FileOutputStream;

import java.io.IOException;

/**

* 使用DataOutputStream書寫具有一定格式的檔案

*/

public class WriteFileUseDataStream {

public static void main(String[] args){

short[] sh = {1,3,134,12};

MyData data = new MyData(true,100,"Java語言",sh);

//寫入檔案

writeFile(data);

}

/**

* 將MyData對象按照一定格式寫入檔案中

* @param data 資料對象

*/

public static void writeFile(MyData data){

FileOutputStream fos = null;

DataOutputStream dos = null;

try{

//建立檔案流

fos = new FileOutputStream("test.my");

//建立資料輸出資料流,流的嵌套

dos = new DataOutputStream(fos);

//依次寫入資料

dos.writeBoolean(data.b);

dos.writeInt(data.n);

dos.writeUTF(data.s);

//寫入數組

int len = data.sh.length;

dos.writeInt(len); //數組長度

//依次寫入每個數組元素

for(int i=0;i<len;++i)

dos.writeShort(data.sh[i]);

}catch(Exception e){

e.printStackTrace();

}finally{

try {

dos.close();

fos.close();

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

}

//ReadFileUseDataStream.java

import java.io.DataInputStream;

import java.io.FileInputStream;

/**

* 使用DataInputStream讀取自訂格式的檔案

*/

public class ReadFileUseDataStream {

public static void main(String[] args) {

MyData data = readFile();

System.out.println(data.b);

System.out.println(data.n);

System.out.println(data.s);

int len = data.sh.length;

for(int i=0;i<len;++i)

System.out.println(data.sh[i]);

}

/**

* 從檔案test.my中讀取資料,並使用讀取到的資料初始化data對象

* @return 讀取到的對象內容

*/

public static MyData readFile(){

MyData data = new MyData();

FileInputStream fis = null;

DataInputStream dis = null;

try{

//建立檔案流

fis = new FileInputStream("test.my");

//建立資料輸入流,流的嵌套

dis = new DataInputStream(fis);

//依次讀取資料,並賦值給data對象

data.b = dis.readBoolean();

data.n = dis.readInt();

data.s = dis.readUTF();

int len = dis.readInt();

data.sh = new short[len];

for(int i=0;i<len;++i)

data.sh[i] = dis.readShort();

}catch(Exception e){

e.printStackTrace();

}finally{

try{

dis.close();

fis.close();

}catch(Exception e){

e.printStackTrace();

}

}

return data;

}

}

3. IO類的最主要的橋接流有兩個:InputStreamReader和OutputStreamWriter。前者實現將InputStream及其子類的對象轉換為Reader體系類的對象,實現將位元組輸入資料流轉換為字元輸入資料流;後者實現將OutputStream及其子類的對象轉換為Writer體系類的對象,實現將位元組輸入資料流轉換為字元輸入資料流。需要注意的是,字元流無法轉換為位元組流。

4. IO類中有一組提高 讀寫效率的類,包括BufferedInputStream/BufferedOutputStream、BufferedReader/BufferedWriter。使用樣本如下,該代碼實現的功能是如果回顯使用者輸入,當使用者輸入quit時程式退出。:

import java.io.BufferedReader;

import java.io.InputStreamReader;

public class ReadConsoleWithBuffer {

public static void main(String[] args) {

BufferedReader br = null;

String s = null;

try{

//使用流的嵌套構造緩衝流

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

do{

//輸出提示資訊

System.out.println("請輸入:");

//按行讀取輸入

s = br.readLine();

//輸出使用者輸入

System.out.println(s);

}while(!s.equals("quit"));

}catch(Exception e){

e.printStackTrace();

}finally{

try{

br.close();

}catch(Exception e){

e.printStackTrace();

}

}

}

}

三、標準I/O

1. java.lang.System類提供了三個靜態變數:

a) System.in:為InputStream類型,代表標準輸入資料流,預設的資料來源為鍵盤。

b) System.out:為PrintStream類型,代表標準輸出資料流,預設的資料來源為控制台。

c) System.err:為PrintStream類型,代表標準錯誤輸出資料流,預設的資料來源是控制台。

2. System類提供了一些用於重新導向流的靜態方法:

a) setIn(InputStream in):對標準輸入資料流重新導向。

b) setout(PrintStream out):對標準輸出資料流重新導向。

c) setErr(PrintStream out):對標準錯誤輸出資料流重新導向。

四、對象的序列化和還原序列化

1. 只有實現了java.io.Serializable介面的類的對象才能被序列化和還原序列化。JDK類庫中的有些類(比如String類、封裝類和Date類等)都實現了Serializable介面。

2. 對象的序列化包括以下步驟:

a) 建立一個對象輸出資料流,它可以封裝一個其他類型的輸出資料流。

b) 通過對象輸出資料流的writeObject()方法寫對象。

3. 對象的還原序列化包括以下步驟:

a) 建立一個對象輸入資料流,它可以封裝一個其他類型的輸入資料流。

b) 通過對象輸入資料流的readObject()方法讀取對象。

4. 必須保證向對象輸出資料流寫對象的順序與從對象輸入資料流讀對象的順序一致。

5. 通過,對象中的所有屬性都會被序列化,對於一些比較敏感的資訊(比如使用者的口令),應該禁止對這種屬性進行序列化。解決的辦法是把這些屬性用transient修飾,這樣它就不會參與序列化及還原序列化過程。

6. 如果希望進一步控制序列化及還原序列化的方式,可以在類中提供一個readObject()和writeObject()方法,當ObjectOutputStream/ObjectInputStream對一個對象進行序列化和還原序列化時,如果該對象具有writeObject()或readObject()方法時,就會執行這一方法,否則就按預設序列化和還原序列化。在writeObject()方法中可以調用ObjectOutputStream的defaultWriteObject()方法,使得對象輸出資料流執行預設序列化操作;在readObject()方法中可以調用ObjectInputStream的defaultReadObject()方法,使得對象輸入資料流執行預設還原序列化操作。以下是範例程式碼:

import java.io.ByteArrayInputStream;

import java.io.ByteArrayOutputStream;

import java.io.IOException;

import java.io.ObjectInputStream;

import java.io.ObjectOutputStream;

import java.io.Serializable;

public class User implements Serializable{

private String name;

private transient String password;

public User(String name,String password){

this.name = name;

this.password = password;

}

public String toString(){

return name+" "+password;

}

/**

* 加密數組,將buff數組中的每個位元組的每一位取反

* 例如13的二進位形式為00001101,取反後為11110010

*/

private byte[] change(byte[] buff){

for(int i=0;i<buff.length;++i){

int b = 0;

for(int j=0;j<8;++j){

int bit = (buff[i]>>j & 1) == 0 ? 1 : 0;

b += (1<<j)*bit;

}

buff[i] = (byte)b;

}

return buff;

}

private void writeObject(ObjectOutputStream stream) throws IOException{

stream.defaultWriteObject(); //先按預設序列化

stream.writeObject(change(password.getBytes()));

}

private void readObject(ObjectInputStream stream) throws IOException,ClassNotFoundException{

stream.defaultReadObject(); //先按預設還原序列化

byte[] buff = (byte[])stream.readObject();

password = new String(change(buff));

}

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

User user = new User("Tom","123456");

System.out.println("Before Serializable:"+user);

ByteArrayOutputStream buf = new ByteArrayOutputStream();

//把User對象序列化到一個位元組緩衝中

ObjectOutputStream o = new ObjectOutputStream(buf);

o.writeObject(user);

//從位元組緩衝中還原序列化User對象

ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(buf.toByteArray()));

user = (User)in.readObject();

System.out.println("After Serializable:"+user);

}

}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.