Java中把不同的輸入輸出源(鍵盤,檔案,網絡)抽象為流。
流可分為輸入輸出流。
流又分為字元流和位元組流兩大類。
Java輸入流主要是由InputStream和Reader作為基類。輸出流主要是OutputStream和Writer作為基類。
它們都是抽象基類無法建立執行個體。
位元組流主要以InputStream和OutputStream作為基類。而字元流則主要以Reader和Writer作為基類。
可以從一個特定的IO裝置(如鍵盤,網絡)讀寫的流成為位元組流,會和檔案關聯。也稱為低級流(Low Level Stream)。
對一個流進行封裝後的流稱為處理流,也成為進階流。
InputStream 和 Reader分别有一個用于讀取檔案的輸入流:FileInputStream 和 FileReader,它們都是位元組流。
--------------------------------------------------------------------------------
InputStream包含的三個方法:
(1)int read() 讀取單個位元組。
(2)int read(byte[] b) 最多讀取b.length的位元組,并将其存儲在數組b中。傳回實際讀取的位元組數。
(3)int read(byte[] b,int of,int len) 此時讀取的起點從off開始。
Reader的三個方法
(1)int read() 讀取單個字元,字元資料可以直接轉換為int類型。
(2)int read(char[] cbuf) 最多讀取cbuf.length個字元
(3)int read(char[] cbuf,int off,int len) 從off位置開始讀。
InputStream和Reader還支援移動記錄指針:
(1)void mark(int readAheadLimit): 在記錄指針目前位置記錄一個标記(mark)
(2)boolean markSupport(): 判斷目前流是否支援記錄标記;
(3)void reset(): 将記錄指針重定位到上一個标記。
(4)long skip(long n): 将記錄指針向前移動n個位元組/字元
----------------------------------------------------------------------------------
OutputStream 和 Writer都包含如下三個方法:
(1)void write(int c): 将指定位元組/字元輸出到流中。
(2)void write(byte[]/char[] buf): 将位元組數組/字元數組輸出到流中
(3)void write(byte[]/char[] buf, int off, int len): 将位元組數組/字元數組從off位置開始,長度為len的位元組/字元輸出到流中。
此外,因為字元流以字元為機關,是以Writer還支援用字元串來代替字元數組。包含如下方法:
(1)void write(Strng str): 将字元串包含的字元輸出到流中
(2)void write(Sring str,int off,int len): 将字元串從off位置開始,長度為len的字元輸出到流中。
try {
/** 擷取檔案輸入流 */
FileInputStream fis = new FileInputStream(file);
/** 讀取檔案 */
while ((length = fis.read(buffer)) > 0) {
// 需要将字元數組轉化為字元串後輸出,不然輸出的是亂碼,轉成字元串後中文仍是亂碼
System.out.println("----" + buffer);
System.out.println("----" + new String(buffer, "utf-8"));
System.out.println("----" + new String(buffer, 0, length));// offset
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
============================================
上面介紹了輸入輸出流的4個抽象基類,并介紹了4個通路檔案節點流的方法。使用比較繁瑣。
處理流進行輸入輸出更簡單,效率也更高。
通常認為位元組流要比字元流更為強大,因為計算機中是以資料都是二進制的,而位元組流可以處理所有二進制檔案。但轉換成字元就複雜了。是以一般:如果輸入輸出是文本内容則用字元流,如果輸入輸出是二進制,則用位元組流。
四個抽象基類: InputStream OutputStream Reader Writer
對應四個節點流方法: FileInputStream FileOutputStream FileReader FileWriter
處理流 : PrintStream 用來包裝InputStream (包括FileInputStream) 如果需要輸入文本,最好就用處理流。關閉上層的處理流,系統會自動關閉對應的節點流。
轉換流 : InputStreamReader : 把位元組流轉換成字元輸入流 InputStreamWriter 把位元組流轉換成字元輸出流
System.in 代表鍵盤輸入流,但其是Inputstream的執行個體,使用不友善,可以包裝成InputStreamReader 将其轉換為字元輸入流,普通的Reader讀取内容時不友善,可以轉化為BufferReader利用BufferReader的readLine()可以一次讀取一行。
/** 用轉換流就可以不亂碼了。windows使用的gbk,linux平台上中文一般utf-8. 根據tmp.txt的編碼類型來選擇 */
fis = new FileInputStream(file);
InputStreamReader reader = new InputStreamReader(fis, "gbk");
BufferedReader br = new BufferedReader(reader);
String readStr = null;
while ((readStr = br.readLine()) != null) {
System.out.println("-----: " + readStr);
}
自動解析編碼:
public String convertCodeAndGetText(String str_filepath) {// 轉碼
File file = new File(str_filepath);
BufferedReader reader;
String text = "";
try {
// FileReader f_reader = new FileReader(file);
// BufferedReader reader = new BufferedReader(f_reader);
FileInputStream fis = new FileInputStream(file);
BufferedInputStream in = new BufferedInputStream(fis);
in.mark(4);
byte[] first3bytes = new byte[3];
in.read(first3bytes);//找到文檔的前三個位元組并自動判斷文檔類型。
in.reset();
if (first3bytes[0] == (byte) 0xEF && first3bytes[1] == (byte) 0xBB
&& first3bytes[2] == (byte) 0xBF) {// utf-8
reader = new BufferedReader(new InputStreamReader(in, "utf-8"));
} else if (first3bytes[0] == (byte) 0xFF
&& first3bytes[1] == (byte) 0xFE) {
reader = new BufferedReader(
new InputStreamReader(in, "unicode"));
} else if (first3bytes[0] == (byte) 0xFE
&& first3bytes[1] == (byte) 0xFF) {
reader = new BufferedReader(new InputStreamReader(in,
"utf-16be"));
} else if (first3bytes[0] == (byte) 0xFF
&& first3bytes[1] == (byte) 0xFF) {
reader = new BufferedReader(new InputStreamReader(in,
"utf-16le"));
} else {
reader = new BufferedReader(new InputStreamReader(in, "GBK"));
}
String str = reader.readLine();
while (str != null) {
text = text + str + "/n";
str = reader.readLine();
}
reader.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return text;
}