原文鏈接http://zhhll.icu/2020/05/18/java%E5%9F%BA%E7%A1%80/IO/java%E5%9F%BA%E7%A1%80%E4%B9%8BIO%E6%93%8D%E4%BD%9C/
用戶行程發起請求,內核接收到請求后,從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
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/246719.html
標籤:Java
