IO操作
使用者程序發起請求,核心接收到請求後,從I/O裝置中獲取資料到buffer中,再將buffer中的資料copy到使用者程序的地址空間,該使用者程序獲取到資料後再響應客戶端。
資料輸入到buffer需要時間,從buffer複製資料至程序也需要時間,根據在這兩段時間內等待方式不同,I/O動作可分為五種模式
- 阻塞I/O(Blocking I/O)
- 非阻塞I/O(Non-Blocking I/O)
- I/O複用(I/O Multiplexing)
- 訊號驅動I/O
- 非同步I/O
java的I/O操作在類的java.io包中
-
基於位元組操作的I/O介面: InputStream和OutputStream
-
基於字元操作的I/O介面: Writer和Reader
-
基於磁碟操作的I/O介面: File
-
基於網路操作的I/O介面: Socket(網路程式設計,不在io包中)
普通IO
-
位元組流對應原生的二進位制資料
-
字元流對應字元資料,會自動處理與本地字符集之間的轉換
-
緩衝流可以提高效能,通過減少底層API的呼叫次數來優化IO
位元組流
輸入流
位元組輸入流都繼承自InputStream,InputStream表示從不同資料來源產生輸入的類,這些資料員包括
- 位元組陣列
- String物件
- 檔案
- 管道,從一端輸入,從另一端輸出
- 一個由其他種類的流組成的序列,然後把它們匯聚為一個流
- 其他資料來源,如Internet連線
類 | 功能 | 構造器 | 如何使用 |
---|---|---|---|
ByteArrayInputStream | 允許將記憶體的緩衝區當做InputStream使用 | 緩衝區,位元組將從中取出 | 將其與FilterInputStream物件相連以提供有用介面 |
StringBufferInputStream | 將String轉換為InputStream | 字串。底層實現實際使用StringBuffer | 將其與FilterInputStream物件相連以提供有用介面 |
FileInputStream | 用於從檔案中讀取資訊 | 字串,表示檔名、檔案或FileDescriptor物件 | |
PipedInputStream | 產生用於寫入相關PipedOutputStream的資料。實現管道化概念 | PipedOutputStream | 作為多執行緒中的資料來源 |
SequenceInputStream | 將兩個或多個InputStream物件轉換成一個InputStream | 兩個InputStream物件或一個容納InputStream物件的容器Enumeration | |
FilterInputStream | 抽象類,作為裝飾器的介面,為其他的InputStream類提供有用的功能 |
FilterInputStream型別子類包括以下幾種
類 | 功能 | 構造器 | 如何使用 |
---|---|---|---|
DataInputStream | 與DataOutputStream搭配使用,按照移植方式從流讀取基本資料型別 | InputStream | 包含用於讀取基本資料型別的全部介面 |
BufferedInputStream | 使用它可以防止每次讀取時都得進行實際寫操作 | InputStream | 本質上不提供介面,只是向程序新增緩衝功能 |
LineNumberInputStream | 跟蹤輸入流的行號,可呼叫getLineNumber()和setLineNumber(int) | InputStream,可以指定緩衝區大小 | 僅增加了行號 |
PushbackInputStream | 具有能彈出一個位元組的緩衝區,因此可以將讀到的最後一個字元回退 | InputStream | 通常作為編譯器的掃描器 |
輸出流
位元組輸入流都繼承自OuputStream,該類決定了輸出所要去的目標,位元組陣列、檔案或管道
類 | 功能 | 構造器 | 如何使用 |
---|---|---|---|
ByteArrayOutputStream | 在記憶體中建立緩衝區。所有送往流的資料都要放置在此緩衝區 | 緩衝區初始大小 | 用於指定資料的目的地 |
FileOutputStream | 用於將資訊寫入檔案 | 字串,表示檔名、檔案或FileDescriptor物件 | |
PipedOutputStream | 任何寫入其中的資訊都會自動作為相關PipedInputStream的輸出,實現管道化概念 | PipedInputStream | 指定用於多執行緒的資料的目的地 |
FilterOutputStream | 抽象類,作為裝飾器的介面,為其他OutputStream提供有用的功能 |
FilterOutputStream型別子類包括
類 | 功能 | 構造器 | 如何使用 |
---|---|---|---|
DataOutputStream | 與DataInputStream搭配使用,可以按照移植方式向流中寫入基本資料型別 | OutputStream | 包含用於寫入基本資料型別的全部介面 |
PrintStream | 用於產生改格式化輸出。其中DataOutputStream處理資料的儲存,PrintStream處理顯示 | OutputStream,可以用boolean值指示是否每次換行時清空緩衝區 | 應該是對OutputStream物件的final封裝 |
BufferedOutputStream | 使用它以避免每次傳送資料時都進行實際的寫操作,可以呼叫flush()清空緩衝區 | OutputStream,可以指定緩衝區大小 | 只是向程序新增緩衝功能 |
字元流
InputStream和OutputStream是面向位元組I/O的,而Reader和Writer則提供相容Unicode和麵向字元I/O的功能,InputStreamReader可以把InputStream轉換為Reader,而OutputStreamWriter可以把OutputStream轉換為Writer
RandomAccessFile類
適用於由大小已知的記錄組成的檔案,可以使用seek()將檔案指標從一條記錄移動到另一條記錄,然後對記錄進行讀取和修改。檔案中記錄的大小不一定相同,只要我們能確定那些記錄有多大以及它們在檔案中的位置即可。
RandomAccessFile類不是InputStream或者OutputStream的子類,只是實現了DataInput和DataOutput介面,沒有使用InputStream和OutputStream的任何功能,所有方法都是獨立的,大部分為native方法
常用的IO操作
緩衝輸入檔案
想要開啟一個檔案進行字元輸入,可以使用FileReader物件,然後傳入一個String或者File物件作為檔名。為了提高速度,對檔案進行緩衝,可以將所產生的引用傳遞給一個BufferedReader構造器。BufferedReader提供了lines()方法,會產生一個Stream
public static void read(String file) {
try(BufferedReader bufferedReader = new BufferedReader(new FileReader(file))){
String line = null;
while((line = bufferedReader.readLine()) != null){
System.out.println(line);
}
} catch (IOException e) {
throw new RuntimeException("讀取失敗",e);
}
}
讀取字元
public static void read() throws IOException {
StringReader stringReader = new StringReader("qaw試試");
int c;
while ((c = stringReader.read()) != -1) {
System.out.println((char)c);
}
}
StringReader的read方法是以int形式返回的下一個位元組,所以列印的時候型別必須轉為char
格式化資料
要讀取格式化資料,可以使用DataInputStream,是面向位元組的,所以要使用InputStream類
檔案輸出
FileWrite物件用於向檔案寫入資料,通常使用BufferedWriter將其包裝起來增加緩衝的功能,
try(BufferedReader in = new BufferedReader(new StringReader("1111111111111111\n2222222222222\n3333333333"));
PrintWriter printWriter = new PrintWriter(new BufferedWriter(new FileWriter("test.txt")))
){
in.lines().forEach(printWriter :: println);
} catch (IOException e) {
e.printStackTrace();
}
標準IO
標準輸入流Systom.in、標準輸出流System.out、標準錯誤流Sytem.err。
System.out和System.err是預先包裝成了PrintStream物件,但是System.in沒有進行包裝,屬於原生的InputStream,所以在讀取時需要對其進行包裝
標準輸入
通常一行一行地讀取輸入,將System.in包裝成BufferedReader
public static void main(String[] args) {
try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in))) {
String line;
while ((line = bufferedReader.readLine()) != null) {
if (line.equals("end")) {
break;
}
System.out.println(line);
}
} catch (IOException e) {
}
}
重定向標準I/O
System類提供了簡單的靜態方法呼叫,重定向標準輸入流、標準輸出流和標準錯誤流
-
setIn(InputStream)
-
setOut(PrintStream)
-
setErr(PrintStream)
public static void main(String[] args) {
try(BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream("C:\\Users\\sinosoft\\Desktop\\剩餘工作.txt"));
PrintStream printStream = new PrintStream(new BufferedOutputStream(new FileOutputStream("C:\\Users\\sinosoft\\Desktop\\剩餘工作副本.txt")))
){
System.setIn(bufferedInputStream);
System.setOut(printStream);
try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in))) {
String line;
while ((line = bufferedReader.readLine()) != null) {
if (line.equals("end")) {
break;
}
System.out.println(line);
}
} catch (IOException e1) {
}
}catch (IOException e){
}
}
由於本身的部落格百度沒有收錄,部落格地址http://zhhll.icu