thinking in java (二十九) ----- IO之 InputStreamReader和OutputStreamWriter
阿新 • • 發佈:2018-11-16
InputStreamReader和OutputStreamWriter介紹
InputStreamReader和OutputStreamWriter是位元組通往字元的橋樑,它使用指定的charset讀取位元組並將其解碼為字元。
InputStreamReader的作用是將位元組輸入流轉換為字元輸入流,繼承於Reader
OutputStreamWriter的作用是將位元組輸出流轉換為字元輸出流,繼承於WriterOutputStreamWriter
InputStreamReader和OutputStreamWriter原始碼
InputStreamReader原始碼
package java.io; import java.nio.charset.Charset; import java.nio.charset.CharsetDecoder; import sun.nio.cs.StreamDecoder; // 將“位元組輸入流”轉換成“字元輸入流” public class InputStreamReader extends Reader { private final StreamDecoder sd; // 根據in建立InputStreamReader,使用預設的編碼 public InputStreamReader(InputStream in) { super(in); try { sd = StreamDecoder.forInputStreamReader(in, this, (String)null); // ## check lock object } catch (UnsupportedEncodingException e) { // The default encoding should always be available throw new Error(e); } } // 根據in建立InputStreamReader,使用編碼charsetName(編碼名) public InputStreamReader(InputStream in, String charsetName) throws UnsupportedEncodingException { super(in); if (charsetName == null) throw new NullPointerException("charsetName"); sd = StreamDecoder.forInputStreamReader(in, this, charsetName); } // 根據in建立InputStreamReader,使用編碼cs public InputStreamReader(InputStream in, Charset cs) { super(in); if (cs == null) throw new NullPointerException("charset"); sd = StreamDecoder.forInputStreamReader(in, this, cs); } // 根據in建立InputStreamReader,使用解碼器dec public InputStreamReader(InputStream in, CharsetDecoder dec) { super(in); if (dec == null) throw new NullPointerException("charset decoder"); sd = StreamDecoder.forInputStreamReader(in, this, dec); } // 獲取解碼器 public String getEncoding() { return sd.getEncoding(); } // 讀取並返回一個字元 public int read() throws IOException { return sd.read(); } // 將InputStreamReader中的資料寫入cbuf中,從cbuf的offset位置開始寫入,寫入長度是length public int read(char cbuf[], int offset, int length) throws IOException { return sd.read(cbuf, offset, length); } // 能否從InputStreamReader中讀取資料 public boolean ready() throws IOException { return sd.ready(); } // 關閉InputStreamReader public void close() throws IOException { sd.close(); } }
OutputStreamWriter
package java.io; import java.nio.charset.Charset; import java.nio.charset.CharsetEncoder; import sun.nio.cs.StreamEncoder; // 將“位元組輸出流”轉換成“字元輸出流” public class OutputStreamWriter extends Writer { private final StreamEncoder se; // 根據out建立OutputStreamWriter,使用編碼charsetName(編碼名) public OutputStreamWriter(OutputStream out, String charsetName) throws UnsupportedEncodingException { super(out); if (charsetName == null) throw new NullPointerException("charsetName"); se = StreamEncoder.forOutputStreamWriter(out, this, charsetName); } // 根據out建立OutputStreamWriter,使用預設的編碼 public OutputStreamWriter(OutputStream out) { super(out); try { se = StreamEncoder.forOutputStreamWriter(out, this, (String)null); } catch (UnsupportedEncodingException e) { throw new Error(e); } } // 根據out建立OutputStreamWriter,使用編碼cs public OutputStreamWriter(OutputStream out, Charset cs) { super(out); if (cs == null) throw new NullPointerException("charset"); se = StreamEncoder.forOutputStreamWriter(out, this, cs); } // 根據out建立OutputStreamWriter,使用編碼器enc public OutputStreamWriter(OutputStream out, CharsetEncoder enc) { super(out); if (enc == null) throw new NullPointerException("charset encoder"); se = StreamEncoder.forOutputStreamWriter(out, this, enc); }java io系列01之 "目錄" // 獲取編碼器enc public String getEncoding() { return se.getEncoding(); } // 重新整理緩衝區 void flushBuffer() throws IOException { se.flushBuffer(); } // 將單個字元寫入到OutputStreamWriter中 public void write(int c) throws IOException { se.write(c); } // 將字元陣列cbuf從off開始的資料寫入到OutputStreamWriter中,寫入長度是len public void write(char cbuf[], int off, int len) throws IOException { se.write(cbuf, off, len); } // 將字串str從off開始的資料寫入到OutputStreamWriter中,寫入長度是len public void write(String str, int off, int len) throws IOException { se.write(str, off, len); }java io系列01之 "目錄" // 重新整理“輸出流” // 它與flushBuffer()的區別是:flushBuffer()只會重新整理緩衝,而flush()是重新整理流,flush()包括了flushBuffer。 public void flush() throws IOException { se.flush(); } // 關閉“輸出流” public void close() throws IOException { se.close(); } }
作用就是講位元組流轉換為字元流,他們的原理是,我們建立字元流的時候,需要指定位元組流,和字元編碼方式。
示例程式
package test;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.InputStreamReader;
import java.io.IOException;
/**
* InputStreamReader 和 OutputStreamWriter 測試程式
*
* @author skywang
*/
public class StreamConverter {
private static final String FileName = "file.txt";
private static final String CharsetName = "utf-8";
//private static final String CharsetName = "gb2312";
public static void main(String[] args) {
testWrite();
testRead();
}
/**
* OutputStreamWriter 演示函式
*
*/
private static void testWrite() {
try {
// 建立檔案“file.txt”對應File物件
File file = new File(FileName);
// 建立FileOutputStream對應OutputStreamWriter:將位元組流轉換為字元流,即寫入out1的資料會自動由位元組轉換為字元。
OutputStreamWriter out1 = new OutputStreamWriter(new FileOutputStream(file), CharsetName);
// 寫入10個漢字
out1.write("位元組流轉為字元流示例");
// 向“檔案中”寫入"0123456789"+換行符
out1.write("0123456789\n");
out1.close();
} catch(IOException e) {
e.printStackTrace();
}
}
/**
* InputStreamReader 演示程式
*/
private static void testRead() {
try {
// 方法1:新建FileInputStream物件
// 新建檔案“file.txt”對應File物件
File file = new File(FileName);
InputStreamReader in1 = new InputStreamReader(new FileInputStream(file), CharsetName);
// 測試read(),從中讀取一個字元
char c1 = (char)in1.read();
System.out.println("c1="+c1);
// 測試skip(long byteCount),跳過4個字元
in1.skip(6);
// 測試read(char[] cbuf, int off, int len)
char[] buf = new char[10];
in1.read(buf, 0, buf.length);
System.out.println("buf="+(new String(buf)));
in1.close();
} catch(IOException e) {
e.printStackTrace();
}
}
}
執行結果:
c1=字
buf=流示例0123456
結果說明:
(01) testWrite() 的作用是將“內容寫入到輸出流”。寫入的時候,會將寫入的內容轉換utf-8編碼並寫入。
(02) testRead() 的作用是將“內容讀取到輸入流”。讀取的時候,會將內容轉換成utf-8的內容轉換成位元組並讀出來。
生成的檔案utf-8的file.txt的16進位制效果圖如下:
將StreamConverter.java中的CharsetName修改為"gb2312"。執行程式,生產的file.txt的16進位制效果圖如下: