爲了弄懂`Writer`與`OutputStream`的區別,首先要理解字節和字符(或者字節流和字符流)的區別;關於字節和字符的知識,我想Java 中字節流與字符流的區別?這篇文章已經將得非常詳細了。
本文則從應用上做簡單的補充:
首先以writer()方式向一個文件中寫入一個字符串,由於writer()是爲字符流設定的,所以在寫入的時候我們可以指定字符串寫入的編碼格式,這裏採用“UTF-16”格式:
private static void write(){
File file = new File("./","write.txt");
if (file.exists()){
file.delete();
}
try {
file.createNewFile();
PrintWriter printWriter = new PrintWriter(new OutputStreamWriter(new FileOutputStream(file), Charset.forName("UTF-16")));
printWriter.print("使用printWriter");
printWriter.println();
char[] charArray = { '使', '用', 'a', 'b', 'c' };
printWriter.print(charArray);
printWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
然後我們打開`write.txt`文件的二進制內容:
如上圖,4F7E即爲“使”字的Unicode的編碼,而文件頭的`FEFF`則表明此文件中的數據流爲大端模式(高位在低地址,低位在高地址),另外我們也可以看到Java默認的字符編碼爲UTF-16。
然後,再使用OutputStream實現類之一的FileOuptStream,對文件進行寫入:
private static void stream(){
File file = new File("./", "stream.txt");
if (file.exists()){
file.delete();
}
try {
file.createNewFile();
OutputStream outputStream = new FileOutputStream(file);
outputStream.write("使用OutputStream".getBytes());
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
然後,打開"stream.txt",可以看出
E4 BD BF = 11100100 10111101 10111111 (UTF-8)
(Unicode) 01001111 01111111 = 4F7F。
getBytes()在不設置Charset參數時默認獲取字符串的UTF-8字節數組。
在使用上Writer與OutputStream兩者的區別則是,writer是用於寫字符流的,所以不能直接接受byte[],OutputStream的實現類則是不直接接受字符流。同理,read()方法在reader中讀出一個字符(char),在InputStream中讀出一個byte。
然而,我們在使用InputStream時總是有 i = inputStream.read();(int i = 0),此時的read()讀出一個byte並將byte賦值給i, i的最後一個byte即是read()讀出的內容,我們使用 outputStream.wirite(int i),時,實際就是將i的最後一個byte寫入。
所以,當需要批量讀取時,Writer、Reader使用char[],InputStream、OutputStream使用byte[]。