一、介紹
流是數據源或數據目標的輸入或輸出設備的抽象表示。支持流輸入和輸出的主要包是java.io,但是也有其他的包,比如java.nio.file。java.io包支持兩種類型的流——包含二進制數據的字節流和包含字符數據的字符流。
當寫數據到字節流中時,數據會以字節序列的形式寫到流中,與它們在內存中的形式完全一樣,在這個過程中不會發生數據轉換。即java.io包中的InputStream和OutputStream的派生類,通常用來讀取二進制數據,如圖像和聲音。
將字符串作為字符數據讀入流時,默認Unicode字符會首先被自動轉化成主機的本地字符表示,之后再寫到流中。包括Reader和Writer類。字符流用於存儲和提取文本,也可以使用字符流讀取由非java程序創建的文本文件。
但是,Read和Write並不是取代InputStream和OutputStream,有時,你還必須同時使用"基於byte的類"和"基於字符的類"。為此,它還提供了兩個"適配器(adapter)"類。InputStreamReader負責將InputStream轉化成Reader,而OutputStreamWriter則將OutputStream轉化成Writer。
二、字節流
包java.io中的兩個類InputStream和OutputStream,java基於他們對流I/O操作提供支持。InputStream和OutputStream都是抽象類,無法創建實例,但是可以用於派生具有更加實際輸入輸出功能的類。這兩個類都實現了Closeable接口,而Closeable接口只聲明了方法close()——關閉流並且釋放流對象保存的所有資源。
1、InputStream類
InputStream包含三個read()方法用於從流中讀取數據:
public abstract int read(); 抽象方法,以int類型返回流中可用的下一個字節。讀取到末尾,返回-1。
public int read(byte[] array); 該方法從流中讀取字節填充到數組array的連續元素中,最大讀取長度為array.length個字節。讀取到末尾,返回-1。
public int read(byte[] array, int offset, int length); 該方法從流中讀取length長度的字節填充到數組array中,將array[offset]作為存放起始位置。讀取到末尾,返回-1。
public int available(); 返回輸入流中可以讀取的字節數。注意:若輸入阻塞,當前線程將被掛起,如果InputStream對象調用這個方法的話,它只會返回0,這個方法必須由繼承InputStream類的子類對象調用才有用。
public long skip(long n); 忽略輸入流中的n個字節,返回值是實際忽略的字節數, 跳過一些字節再讀取。
如果發生I/O類型錯誤,會拋出IOException類型的異常。
InputStream類的派生類結構:
2、OutputStream類
OutputStream提供了3個write()方法來輸出數據,和InputStream相對應:
public abstract void write(int b); 先將int轉換成byte類型,把低字節寫入到輸出流中。
public void write(byte[] array); 將數組array中的字節寫到輸出流。
public void write(byte[] array, int offset, int length); 將數組array中從array[offset]開始的length個字節寫到輸出流。
public void flush(); 將數據緩沖區中數據全部輸出,並清空緩沖區。
如果發生I/O類型錯誤,會拋出IOException類型的異常。
OutputStream類的派生類結構:
3、FileInputStream類
FileInputStream類是InputStream類的子類,用來處理以文件作為數據輸入源的數據流。
使用方法:
方式1:
File fin=new File("d:/abc.txt");
FileInputStream in=new FileInputStream(fin);
方式2:
FileInputStream in=new FileInputStream("d: /abc.txt");
方式3:
構造函數將 FileDescriptor()對象作為其參數。
FileDescriptor() fd=new FileDescriptor();
FileInputStream f2=new FileInputStream(fd);
如果發生I/O類型錯誤,會拋出IOException類型的異常。
4、FileOutputStream類
FileOutputStream類用來處理以文件作為數據輸出目的數據流;一個表示文件名的字符串,也可以是File或FileDescriptor對象。
創建一個文件流對象方法:
方式1:
File f=new File("d:/abc.txt");
FileOutputStream out=new FileOutputStream (f);
方式2:
FileOutputStream out=new
FileOutputStream("d:/abc.txt");
方式3:構造函數將 FileDescriptor()對象作為其參數。
FileDescriptor() fd=new FileDescriptor();
FileOutputStream f2=new FileOutputStream(fd);
方式4:構造函數將文件名作為其第一參數,將布爾值作為第二參數。
FileOutputStream f=new FileOutputStream("d:/abc.txt",true);
如果發生I/O類型錯誤,會拋出IOException類型的異常。
使用過程:
(1)生成文件流對象(對文件讀操作時應該為FileInputStream類,而文件寫應該為FileOutputStream類);
(2)調用FileInputStream或FileOutputStream類中的功能函數如read()、write(int b)等)讀寫文件內容;
(3)關閉文件close()。
注意:
(1)文件中寫數據時,若文件已經存在,則覆蓋存在的文件;
(2)的讀/寫操作結束時,應調用close方法關閉流。
例子:利用FileInputStream讀取一個文件,並存入緩存中,然后通過FileOutputStream寫到一個新的文件
1 import java.io.*; 2 3 public class FileStreamDemo { 4 public static void main(String[] args) throws IOException { 5 6 //創建兩個文件,face.gif是已經存在文件,newFace.gif是新創建的文件 7 File inFile = new File("1.gif"); 8 File outFile = new File("new1.gif"); 9 10 //創建流文件讀入與寫出類 11 FileInputStream inStream = new FileInputStream(inFile); 12 FileOutputStream outStream = new FileOutputStream(outFile); 13 14 //通過available方法取得流的最大字符數 15 byte[] b = new byte[inStream.available()]; 16 inStream.read(b); //讀入流,保存在byte數組 17 outStream.write(b); //寫出流,保存在文件newFace.gif中 18 19 inStream.close(); 20 outStream.close(); 21 } 22 }
5、File類
File類與InputStream / OutputStream類同屬於一個包,它不允許訪問文件內容。
File類主要用於命名文件、查詢文件屬性和處理文件目錄。
6、從一個流構造另一個流
java的流類提供了結構化方法,如,底層流和高層過濾流。而高層流不是從輸入設備讀取,而是從其他流讀取。同樣高層輸出流也不是寫入輸出設備,而是寫入其他流。
使用"分層對象(layered objects)",為單個對象動態地,透明地添加功能的做法,被稱為Decorator Pattern。Decorator模式要求所有包覆在原始對象之外的對象,都必須具有與之完全相同的接口。這使得decorator的用法變得非常的透明--無論對象是否被decorate過,傳給它的消息總是相同的。這也是Java I/O類庫要有"filter(過濾器)"類的原因:抽象的"filter"類是所有decorator的基類。Decorator模式常用於如下的情形:如果用繼承來解決各種需求的話,類的數量會多到不切實際的地步。Java的I/O類庫需要提供很多功能的組合,於是decorator模式就有了用武之地。
為InputStream和OutputStream定義decorator類接口的類,分別是FilterInputStream和FilterOutputStream。
FilterInputStream的種類:
DataInputStream:與DataOutputStream配合使用,這樣你就能以一種"可攜帶的方式(portable fashion)"從流里讀取primitives了(int,char,long等)
BufferedInputStream:用這個類來解決"每次要用數據的時候都要進行物理讀取"的問題。意思是"用緩沖區"。
LineNumberInputStream:跟蹤輸入流的行號;有getLineNumber( )和setLineNumber(int)方法
PushbackInputStream:有一個"彈壓單字節"的緩沖區(has a one byte push-back buffer),這樣你就能把最后讀到的那個字節再壓回去了。
FilterOutputStream的種類:
DataOutputStream:與DataInputStream配合使用,這樣你就可以用一種"可攜帶的方式(portable fashion)"往流里寫primitive了(int, char, long,等)
PrintStream:負責生成帶格式的輸出(formatted output)。DataOutputStrem負責數據的存儲,而PrintStream負責數據的顯示。
BufferedOutputStream:用 這個類解決"每次往流里寫數據,都要進行物理操作"的問題。也就是說"用緩沖區"。用flush( )清空緩沖區。
7、BufferedInputStream類
BufferedInputStream與BufferedOutputStream可以為InputStream、OutputStream類的對象增加緩沖區功能。構建BufferedInputStream實例時,需要給定一個InputStream類型的實例,實現BufferedInputStream時,實際上最后是實現InputStream實例。同樣地,在構建BufferedOutputStream時,也需要給定一個OutputStream實例,實現BufferedOutputStream時,實際上最后是實現OutputStream實例。
BufferedInputStream的數據成員buf是一個位數組,默認為2048字節。當讀取數據來源時,例如文件,BufferedInputStream會盡量將buf填滿。當使用read()方法時,實際上是先讀取buf中的數據,而不是直接對數據來源作讀取。當buf中的數據不足時,BufferedInputStream才會再實現給定的InputStream對象的read()方法,從指定的裝置中提取數據。
方式1:
File srcFile = new File(args[0]);
BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(srcFile));
創建 BufferedInputStream
並保存其參數,即輸入流 in
,以便將來使用。創建一個內部緩沖區數組並將其存儲在 buf
中。
方式2:
File srcFile = new File(args[0]);
BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(srcFile),1024);
創建具有指定緩沖區大小的 BufferedInputStream
,並保存其參數,即輸入流 in
,以便將來使用。創建一個長度為 size
的內部緩沖區數組並將其存儲在 buf
中。
如果發生I/O類型錯誤,會拋出IOException類型的異常。
8、BufferedOutputStream類
BufferedOutputStream的數據成員buf是一個位數組,默認為512字節。當使用write()方法寫入數據時,實際上會先將數據寫至buf中,當buf已滿時才會實現給定的OutputStream對象的write()方法,將buf數據寫至目的地,而不是每次都對目的地作寫入的動作。
方式1:
File desFile = new File(args[1]);
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(desFile));
創建一個新的緩沖輸出流,以將數據寫入指定的基礎輸出流。
方式2:
File desFile = new File(args[1]);
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(desFile),1024);
創建一個新的緩沖輸出流,以將具有指定緩沖區大小的數據寫入指定的基礎輸出流。
如果發生I/O類型錯誤,會拋出IOException類型的異常。
例子:使用BufferedInputStream和BufferedOutputStream復制BuffferedStreamDemo.java的內容至BufferedStreamDemo.txt文件並顯示輸出
1 import java.io.*; 2 3 public class BufferedStreamDemo { 4 5 public static void main(String[] args){ 6 try{ 7 byte[] data=new byte[1]; 8 9 File srcFile=new File("BufferedStreamDemo.java"); 10 File desFile=new File("BufferedStreamDemo.txt");//聲明兩個文件實例 11 12 BufferedInputStream bufferedInputStream=new BufferedInputStream(new FileInputStream(srcFile));//實例化BufferedInputStream 13 BufferedOutputStream bufferedOutputStream=new BufferedOutputStream(new FileOutputStream(desFile));//實例化BufferedOutputStream 14 15 System.out.println("復制文件: "+srcFile.length()+"字節"); 16 //將從BufferedStreamDemo.java文件讀取的字節寫到data,然后再寫到BufferedStreamDemo.txt 17 while(bufferedInputStream.read(data)!=-1){ 18 bufferedOutputStream.write(data); 19 } 20 21 //將緩沖區中的數據全部寫出 22 bufferedOutputStream.flush(); 23 24 System.out.println("復制完成"); 25 26 //顯示輸出BufferedStreamDemo.txt文件的內容 27 bufferedInputStream =new BufferedInputStream(new FileInputStream(new File("BufferedStreamDemo.txt"))); 28 while(bufferedInputStream.read(data)!=-1){ 29 String str=new String(data); 30 System.out.print(str); 31 } 32 33 bufferedInputStream.close(); 34 bufferedOutputStream.close(); 35 36 }catch(ArrayIndexOutOfBoundsException e){ 37 System.out.println("using: java useFileStream src des"); 38 e.printStackTrace(); 39 }catch(IOException e){ 40 e.printStackTrace(); 41 } 42 } 43 }
9、DataInputStream類
DataInputStream和DataOutputStream可提供一些對Java基本數據類型寫入的方法,像讀寫int、double和boolean等的方法。由於Java的數據類型大小是規定好的,在寫入或讀出這些基本數據類型時,就不用擔心不同平台間數據大小不同的問題。
有時沒有必要存儲整個對象的信息,而只是要存儲一個對象的成員數據,成員數據的類型假設都是Java的基本數據類型,這樣的需求不必使用到與Object輸入、輸出相關的流對象,可以使用DataInputStream、DataOutputStream來寫入或讀出數據。
DataInputStream dataInputStream = new DataInputStream(new FileInputStream(args[0]));
方法:
public String readUTF(); 讀入一個已使用UTF-8修改版格式編碼的字符串
public String readLine(); 是通過BufferedReader.readLine()實現的。
public boolean readBoolean;
public int readInt();
public byte readByte();
public char readChar(); 等等一系列讀取基本數據類型的方法
如果發生I/O類型錯誤,會拋出IOException類型的異常。
10、DataOutputStream類
DataOutputStream dataOutputStream = new DataOutputStream(new FileOutputStream(args[0]));
方法:
public void writeBoolean(boolean b); 將一個boolean值以1-byte形式寫入基本輸出流。
public void writeByte(int v); 將一個byte值以1-byte值形式寫入到基本輸出流中。
public void writeBytes(String s); 將字符串按字節順序寫入到基本輸出流中。
public void writeChar(int v); 將一個char值以2-byte形式寫入到基本輸出流中。先寫入高字節。
public void writeInt(int v); 將一個int值以4-byte值形式寫入到輸出流中先寫高字節。
public void writeUTF(String str); 以機器無關的的方式用UTF-8修改版將一個字符串寫到基本輸出流。該方法先用writeShort寫入兩個字節表示后面的字節數。
public int size(); 返回written的當前值。
如果發生I/O類型錯誤,會拋出IOException類型的異常。
例子:先用DataOutputStream想文本寫入各種類型數據,再用DataInputStream從中讀取各種類型數據。
1 import java.io.*; 2 3 public class DataInputStreamDemo { 4 5 private static final int LEN = 5; 6 7 public static void main(String[] args) { 8 // 測試DataOutputStream,將數據寫入到輸出流中。 9 testDataOutputStream() ; 10 // 測試DataInputStream,從上面的輸出流結果中讀取數據。 11 testDataInputStream() ; 12 } 13 14 /** 15 * DataOutputStream的API測試函數 16 */ 17 private static void testDataOutputStream() { 18 19 try { 20 File file = new File("file.txt"); 21 DataOutputStream out = new DataOutputStream(new FileOutputStream(file)); 22 23 out.writeBoolean(true); 24 out.writeByte((byte)0x41); 25 out.writeChar((char)0x4243); 26 out.writeShort((short)0x4445); 27 out.writeInt(0x12345678); 28 out.writeLong(0x0FEDCBA987654321L); 29 out.writeUTF("abcdefghijklmnopqrstuvwxyz嚴12"); 30 31 out.close(); 32 } catch (FileNotFoundException e) { 33 e.printStackTrace(); 34 } catch (IOException e) { 35 e.printStackTrace(); 36 } 37 } 38 /** 39 * DataInputStream的API測試函數 40 */ 41 private static void testDataInputStream() { 42 43 try { 44 File file = new File("file.txt"); 45 DataInputStream in = 46 new DataInputStream( 47 new FileInputStream(file)); 48 49 System.out.printf("byteToHexString(0x8F):0x%s\n", byteToHexString((byte)0x8F)); 50 System.out.printf("charToHexString(0x8FCF):0x%s\n", charToHexString((char)0x8FCF)); 51 System.out.printf("readBoolean():%s\n", in.readBoolean()); 52 System.out.printf("readByte():0x%s\n", byteToHexString(in.readByte())); 53 System.out.printf("readChar():0x%s\n", charToHexString(in.readChar())); 54 System.out.printf("readShort():0x%s\n", shortToHexString(in.readShort())); 55 System.out.printf("readInt():0x%s\n", Integer.toHexString(in.readInt())); 56 System.out.printf("readLong():0x%s\n", Long.toHexString(in.readLong())); 57 System.out.printf("readUTF():%s\n", in.readUTF()); 58 59 in.close(); 60 } catch (FileNotFoundException e) { 61 e.printStackTrace(); 62 } catch (IOException e) { 63 e.printStackTrace(); 64 } 65 } 66 67 // 打印byte對應的16進制的字符串 68 private static String byteToHexString(byte val) { 69 return Integer.toHexString(val & 0xff); 70 } 71 72 // 打印char對應的16進制的字符串 73 private static String charToHexString(char val) { 74 return Integer.toHexString(val); 75 } 76 77 // 打印short對應的16進制的字符串 78 private static String shortToHexString(short val) { 79 return Integer.toHexString(val & 0xffff); 80 } 81 }
三、字符流
包java.io中的兩個類Reader和Writer,他們是能將字節流以字符流方式進行讀寫的對象,因此字符流在本質上是以Reader和Writer封裝的字節流。Reader和Writer都是抽象類,這兩個類都實現了聲明close()方法的AutoCloseable接口。
Reader和Writer類以及他們的子類本身都不是流,但是他們提供了一些方法,可用於將底層的流作為字符流讀寫。因此,通常使用底層的InputStream和OutputStream對象來創建Reader和Writer對象。
1、Reader類
還實現了Readable接口,該接口聲明了read()方法,用於將字符讀入作為參數傳入read()方法的CharBuffer對象。
public int read(); 讀取單個字符。
public int read(char[] cbuf); 讀取多個字符到字符數組cbuf。
public abstract int read(char[] cbuf,int off,int len); 讀取len個字符到字符數組cbuf中,從cbuf[off]開始存放。
public boolean ready(); 這個輸入流是否准備好了。
public void reset(); 重置輸入流。
public long skip(long n); 跳過n個字符讀取。
如果發生I/O類型錯誤,會拋出IOException類型的異常。
Reader類的派生類結構:
2、Writer類
Writer類實現了Appendable接口,聲明了3種版本的append()方法,還有5個write()方法。
public Writer append(char c); 將字符c附加到Writer封裝的任意流后面。
public Writer append(CharSequence csq); 將CharSequence類型的參數附加到底層流的后面。
public Writer append(CharSequence csq, int start, int end); 將一個字符序列的子序列附加到底層流的后面。
public void write(int c); 寫一個單獨的字符。
public void write(String str); 寫一個字符串。
public void write(String str, int off, int len); 寫一個字符串的子串。
public void write(char[] cbuf); 寫一個字符數組。
public abstract void write(char[] cbuf, int off, int len); 寫一個字符數組的子串。
public abstract void flush(); 將數據緩沖區中數據全部輸出,並清空緩沖區。
如果發生I/O類型錯誤,會拋出IOException類型的異常。
Writer類的派生類結構:
3、InputStreamReader類
若想對InputStream和OutputStream進行字符處理,可以使用InputStreamReader和OutputStreamWriter為其加上字符處理的功能,它們分別為Reader和Writer的子類。
舉個例子來說,若想要顯示純文本文件的內容,不用費心地自行判斷字符編碼(例如范例14.15中要費心地自行判斷是ASCII英文字母或BIG5中文字),只要將InputStream、OutputStream的實例作為構建InputStreamReader、OutputStreamWriter時的變量,就可以操作InputStreamReader和OutputStreamWriter來進行文本文件的讀取,讓它們為您做字符判斷與轉換的動作。
如果以文件操作為例,則內存中的字符數據需要通過OutputStreamWriter變為字節流才能保存在文件中,讀取時需要將讀入的字節流通過InputStreamReader變為字符流。過程如下:
寫入數據-->內存中的字符數據-->字符流-->OutputStreamWriter-->字節流-->網絡傳輸(或文件保存)
讀取數據<--內存中的字符數據<--字符流<--InputStreamReader<--字節流<--網絡傳輸(或文件保存)
構造方法:
public InputStreamReader(InputStream in); 創建一個使用默認字符集的 InputStreamReader。
public InputStreamReader(InputStream in, String charsetName); 創建使用指定字符集的 InputStreamReader。
public InputStreamReader(InputStream in, Charset cs); 創建使用指定字符集的 InputStreamReader。
public InputStreamReader(InputStream in, CharsetDecoder dec); 創建使用指定字符集解碼器的 InputStreamReader。
常用Charset:
US-ASCII |
7 位 ASCII 字符,也叫作 ISO646-US、Unicode 字符集的基本拉丁塊 |
ISO-8859-1 |
ISO 拉丁字母表 No.1,也叫作 ISO-LATIN-1 |
UTF-8 |
8 位 UCS 轉換格式 |
UTF-16BE |
16 位 UCS 轉換格式,Big Endian(最低地址存放高位字節)字節順序 |
UTF-16LE |
16 位 UCS 轉換格式,Little-endian(最高地址存放低位字節)字節順序 |
UTF-16 |
16 位 UCS 轉換格式,字節順序由可選的字節順序標記來標識 |
常用方法:
public String getEncoding(); 返回此流使用的字符編碼的名稱。如果該編碼有歷史上用過的名稱,則返回該名稱;否則返回該編碼的規范化名稱。
如果發生I/O類型錯誤,會拋出IOException類型的異常。
4、OutputStreamWriter類
構造方法:
public OutputStreamWriter(OutputStream out); 創建使用默認字符編碼的 OutputStreamWriter。
public OutputStreamWriter(OutputStream out, String charsetName); 創建使用給定字符集的 OutputStreamWriter。
public OutputStreamWriter(OutputStream out, Charset cs); 創建使用給定字符集的 OutputStreamWriter。
public OutputStreamWriter(OutputStream out, CharsetEncoder enc); 創建使用給定字符集編碼器的 OutputStreamWriter。
常用方法:
public String getEncoding(); 返回此流使用的字符編碼的名稱。如果該編碼具有歷史名稱,則返回該名稱;否則返回該編碼的規范化名稱。
如果發生I/O類型錯誤,會拋出IOException類型的異常。
例子:從一個文件中用InputStreamReader讀取,然后將字節流轉換成字符流存在字符串數組;用OutputStreamWriter向另一個文件寫入該數組。
1 import java.io.*; 2 3 public class InputStreamReaderDemo { 4 public static void main(String[] args) throws Exception { // 所有的異常拋出 5 File f1 = new File("helpinfo.txt"); 6 File f2 = new File("test.txt"); 7 Writer out = null; 8 Reader in = null; 9 out = new OutputStreamWriter(new FileOutputStream(f2));// 通過子類實例化父類對象,字節流變為字符流 10 in = new InputStreamReader(new FileInputStream(f1)); 11 char c[] = new char[1024]; 12 in.read(c); 13 System.out.print(c); 14 out.write(c); // 使用字符流輸出 15 in.close(); 16 out.close(); 17 } 18 }
5、FileReader類
FileReader類創建了一個可以讀取字符流文件內容的Reader類。
構造方法:
public FileReader(File file); 在給定從中讀取數據的 File 的情況下創建一個新 FileReader。
public FileReader(String fileName); 在給定從中讀取數據的文件名的情況下創建一個新 FileReader。
public FileReader(FileDescripter fd); 在給定從中讀取數據的 FileDescriptor 的情況下創建一個新 FileReader。
如果發生I/O類型錯誤,會拋出IOException類型的異常。
6、FileWriter類
FileWriter類創建一個可以用字符流寫文件的Writer類。
構造方法:
public FileWriter(File file); 在給出 File 對象的情況下構造一個FileWriter對象。
public FileWriter(File file, boolean append); 在給出File對象的情況下構造一個FileWriter對象,如果第二個參數為true
,則將字節寫入文件末尾處,而不是寫入文件開始處。
public FileWriter(FileDescripter fd); 構造與某個文件描述符相關聯的FileWriter對象。
public FileWriter(String fileName); 在給出文件名的情況下構造一個FileWriter對象。
public FileWriter(String fileName, boolean append); 在給出文件名的情況下構造 FileWriter 對象,如果第二個參數為true
,則將字節寫入文件末尾處,而不是寫入文件開始處。
如果發生I/O類型錯誤,會拋出IOException類型的異常。
例子:從一個文本中讀取字符存在數組中,然后再再到另一個文本。
1 import java.io.*; 2 3 public class FileReaderDemo { 4 public static void main (String args[ ] ) throws Exception { 5 FileReader fr = new FileReader("helpinfo.txt"); 6 FileWriter fw = new FileWriter("test.txt"); 7 char data[]=new char[1024]; 8 int num = fr.read(data); 9 System.out.println(num); 10 fw.write(data); 11 fr.close(); 12 fw.close(); 13 } 14 }
7、BufferedReader類
從字符輸入流中讀取文本,緩沖各個字符,從而提供字符、數組和行的高效讀取。可以指定緩沖區的大小,或者可使用默認的大小。大多數情況下,默認值就足夠大了。通常,Reader 所作的每個讀取請求都會導致對基礎字符或字節流進行相應的讀取請求。因此,建議用 BufferedReader 包裝所有其 read() 操作可能開銷很高的 Reader(如 FileReader 和 InputStreamReader)。例如:BufferedReader in = new BufferedReader(new InputStream(System.in));
構造函數:
public BufferedReader(Reader in); 創建一個使用默認大小輸入緩沖區的緩沖字符輸入流。
public BufferedReader(Reader in, int size); 創建一個使用指定大小輸入緩沖區的緩沖字符輸入流。
常用方法:
public String readline(); 讀取一個文本行,通過下列字符之一即可認為某行已終止:換行 ('\n')、回車 ('\r') 或回車后直接跟着換行。
如果發生I/O類型錯誤,會拋出IOException類型的異常。
8、BufferedWriter類
將文本寫入字符輸出流,緩沖各個字符,從而提供單個字符、數組和字符串的高效寫入。可以指定緩沖區的大小,或者接受默認的大小。在大多數情況下,默認值就足夠大了。該類提供了newLine() 方法,它使用平台自己的行分隔符概念,此概念由系統屬性line.separetor定義。並非所有平台都使用新行符 ('\n') 來終止各行。因此調用此方法來終止每個輸出行要優於直接寫入新行符。通常 Writer 將其輸出立即發送到基礎字符或字節流。除非要求提示輸出,否則建議用 BufferedWriter 包裝所有其 write() 操作可能開銷很高的 Writer(如 FileWriters 和 OutputStreamWriters)。例如,BufferedWriter out = new BufferedWriter(new FileWriter("test.txt"));
構造方法:
public BufferedWriter(Writer out); 創建一個使用默認大小輸出緩沖區的緩沖字符輸出流。
public BufferedWriter(Writer out, int size); 創建一個使用指定大小輸出緩沖區的新緩沖字符輸出流。
常用方法:
public void newline(); 寫入一個行分隔符。行分隔符字符串由系統屬性line.separetor定義,並且不一定是單個新行 ('\n') 符。
如果發生I/O類型錯誤,會拋出IOException類型的異常。
例子:從一個文本中讀取字符存在數組中,然后再再到另一個文本。
1 import java.io.*; 2 3 public class BufferedReaderDemo { 4 5 public static void main(String[] args) { 6 BufferedReader br = null; 7 BufferedWriter bw = null; 8 9 String b = null; 10 File file = new File("abc.txt"); 11 if (!file.exists() != false) { 12 try { 13 file.createNewFile(); 14 } catch (IOException e) { 15 e.printStackTrace(); 16 } 17 } 18 try { 19 bw = new BufferedWriter(new FileWriter(file)); 20 FileReader fr = new FileReader("helpinfo.txt"); 21 br = new BufferedReader(fr); 22 while ((b = br.readLine()) != null) { 23 System.out.println(b); 24 bw.write(b); //輸出字符串 25 bw.newLine();//換行 26 bw.flush(); 27 } 28 } catch (Exception e) { 29 e.printStackTrace(); 30 }finally { 31 try { 32 br.close(); 33 //bw.close(); 34 } catch (IOException e) { 35 e.printStackTrace(); 36 } 37 } 38 } 39 }
四、寫在最后
我寫這篇博客的初衷是讓自己對java的各種I/O有一個更為清楚的認識,所以文中所舉的例子都是一些最為基礎的使用方法。由於編寫時間較短以及本人技術水平有限,所以可能會有一些遺漏和錯誤,大家也可以指出來讓我予以改正。
希望這篇博客不僅能給我,也能給一些像我一樣對java的I/O不清楚的同學一點點幫助。
謝謝!~~~