---
aliases: []
tags:
- java
- io
- PL
- base
created: 2024-01-19 17:01:19
modified: 2024-07-13 11:24:13
---
# Java IO ç¬è®°
---
## IO 模å
Unix/[Linux](../Linux/Linux_Note.md) 䏿 5 ç§ IO 模åï¼
* Blocking IO
* Nonblocking IO
* IO multiplexing
* Signal driven IO
* Asynchronous IO
### ä¸äºæ¦å¿µ
### BIO
BIOï¼BLocking IOï¼é¡¾åæä¹æ¯ä¸ç§é»å¡å IO 模åã
### NIO
NIOï¼Nonblocking IO ï¼ éé»å¡ IO 模åã
### ç¸å
³èµæ
* [çä¸éå°±çè§£ï¼IO模å详解 - æé](https://juejin.cn/post/7036518015462015006)
* [5ç§ç½ç»IO模åï¼æå¾ï¼å¾æ¸
æ¥ï¼ - ç¥ä¹](https://zhuanlan.zhihu.com/p/54580385)
* [ä¸æè¯»æç½ç» IO 模ååç - æé](https://juejin.cn/post/7287791555623190568)
## ä¼ ç» IO
java ä¼ ç» io 使ç¨çæ¯ [BIO](#BIO) 模åã
### IO ç¸å
³ç±»å¾
#### InputStream ç±»å¾
```mermaid
classDiagram
class InputStream {
<>
+read(byte[] b) int
+read(byte[] b, int off, int len) int
}
class FileInputStream {
FileInputStream(File file)
+read(byte[] b) int
+read(byte[] b, int off, int len) int
}
class FilterInputStream {
#FilterInputStream(InputStream in)
+read(byte[] b) int
+read(byte[] b, int off, int len) int
}
class BufferedInputStream {
BufferedInputStream(InputStream in)
BufferedInputStream(InputStream in, int size)
+read(byte[] b, int off, int len) int
}
InputStream <|-- FileInputStream
InputStream <|-- FilterInputStream
FilterInputStream <| -- BufferedInputStream
```
#### OutputStream ç±»å¾
```mermaid
classDiagram
class OutputStream {
<>
+write(byte[] b) void
+write(byte[] b, int off, int len) void
}
class FileOutputStream {
FileOutputStream(File file)
FileOutputStream(File file, boolean append)
FileOutputStream(String name)
FileOutputStream(String name, boolean append)
+write(byte[] b) void
+write(byte[] b, int off, int len) void
}
class FilterOutputStream {
FilterOutputStream(OutputStream out)
+write(byte[] b) void
+write(byte[] b, int off, int len) void
}
class BufferedOutputStream {
BufferedOutputStream(OutputStream out)
BufferedOutputStream(OutputStream out, int size)
+write(byte[] b, int off, int len) void
}
OutputStream <| -- FileOutputStream
OutputStream <| -- FilterOutputStream
FilterOutputStream <| -- BufferedOutputStream
```
### File
Java æé ä¸ä¸ª `File` 对象ï¼å³ä½¿ä¼ å
¥çæä»¶æç®å½ä¸åå¨ï¼ä»£ç ä¹ä¸ä¼åºéï¼å 为è¿ä¸ªå¯¹è±¡åªæ¯ Java å¨å
åä¸æå»ºçä¸ä¸ªå¯¹è±¡ã
å 为æé ä¸ä¸ª `File` 对象ï¼å¹¶ä¸ä¼å¯¼è´ä»»ä½ç£çæä½ï¼èåªæå½è°ç¨ `File` 对象çæäºæ¹æ³çæ¶åï¼æçæ£è¿è¡ IO æä½ã
#### 常è§é®é¢
##### å
³äº File ç空æéå¼å¸¸
示ä¾ï¼
```java
try{
//
File d01 = new File(File_E01.class.getResource("t02.txt").getPath());
// File d01 = new File("t02.txt");
// è·å对象çè·¯å¾
System.out.println(d01.getPath());
// è·å对象çç¶çº§è·¯å¾
System.out.println(d01.getParent());
} catch (NullPointerException e) {
logger.severe("NullPointerException! æä»¶å¯¹å为Null!\n" + e.getMessage());
}
```
å¯ä»¥çææ¡£ç¥éï¼`File` ç±»å¨æå»ºæ¶æå¯è½ä¼æç©ºæéå¼å¸¸ï¼`Throws: NullPointerException - If the pathname argument is null`ï¼ï¼åææ¯é£ä¸ª pathname çå符串为 `null`ã
ä½å®é
ä¸ï¼é¤éæ
æä¼ 个 null å¼ç» File çæé æ¹æ³ï¼åºæ¬ä¸å¯è½è®© File ãnew 空ããå³ä¾¿å¦ä¸é¢ç¤ºä¾ä¸æ ·ï¼ä½¿ç¨ `ç±».class.getResource("xxx").getPath()` è¿ç§æ¹å¼ï¼è·åå°åå¼ãèä¸é¢ç¤ºä¾å´æå¯è½ä¼è§¦åæåºç©ºæéå¼å¸¸ã触åçåå 䏿¯ File çæé æ¹æ³ï¼èæ¯ `ç±».class.getResource("xxx").getPath()` è¿é触åçã
彿§è¡å° `ç±».class.getResource("xxx")` è¿éæ¶ï¼å¦æ `getResource()` çåæ°æ¯ä¸ä¸ªä¸åå¨çè·¯å¾ï¼é£ `getResource()` å°±ä¼è¿å个 nullï¼null æ¯ä¸è½ç»§ç» `getPath()` çï¼æä»¥è§¦åäºç©ºæéå¼å¸¸çæåºãæä»¥å¨è¿ç§æ¹å¼æå»º File 对象ï¼ç©ºæéå¼å¸¸æåºå¨è·¯å¾å符串ãè·åãæ¶å°±æå¯è½è§¦åäºï¼File çæé æ¹æ³æ ¹æ¬æ²¡æºä¼å触å空æéå¼å¸¸ã
è¿æ `ç±».class.getResource("xxx").getPath()` è¿ä»£ç ä¸ç `getPath()` æ¹æ³æ¯ä¸ä¼è¿å Null å¼ï¼å®æå¤åªä¼è¿åä¸ä¸ªç©ºå符串ï¼`Returns: the path part of this `URL`, or an empty string if one does not exist`ï¼ã
#### è·¯å¾ç¸å
³
è·åæä»¶è·¯å¾çæ¹å¼æå¤ç§ï¼
##### æ¹å¼ 1
```java
IO_E01.class.getResource("t01.txt").getPath()
// ç»æä¸getPath()æ¯ä¸è´çï¼ä½toString()ä¸è¬ç¨äºè°è¯
//File_E01.class.getResource("t01.txt").toString()
File_E01.class.getResource("").getPaht() // è¿åçæ¯File_E01ç±»æå¨çç®å½è·¯å¾
```
##### æ¹å¼ 2
```java
System.out.println(this.getClass().getResource(""));
System.out.println(this.getClass().getResource("/"));
System.out.println(this.getClass().getResource("t01.txt"));
System.out.println(this.getClass().getResource("/t01.txt"));
// ç»æ
// file:/home/silascript/DevWorkSpace/JavaExercise/io_exercise/
// file:/home/silascript/DevWorkSpace/JavaExercise/io_exercise/
// file:/home/silascript/DevWorkSpace/JavaExercise/io_exercise/t01.txt
// file:/home/silascript/DevWorkSpace/JavaExercise/io_exercise/t01.txt
```
##### æ¹å¼ 3
```java
System.out.println(this.getClass().getClassLoader().getResource(""));
System.out.println(this.getClass().getClassLoader().getResource("t01.txt"));
System.out.println(this.getClass().getClassLoader().getResource("/"));
System.out.println(this.getClass().getClassLoader().getResource("/t01.txt"));
// ç»æ
// file:/home/silascript/DevWorkSpace/JavaExercise/io_exercise/
// file:/home/silascript/DevWorkSpace/JavaExercise/io_exercise/t01.txt
// null
// null
```
> [!tip]
> `this.getClass().getClassLoader().getResource(è·¯å¾å符串)`ï¼ä½¿ç¨è¿ä¸ªæ¹å¼è·åæä»¶å°åï¼ä¸è½ä»¥ `/`ï¼æ ¹è·¯å¾ï¼å¼å§ï¼ä¸ç¶è¿åå¼åªè½æ¯ `null` ã
>
> å 为 `getClass().getClassLoader()` è¿å·²ç»æ¯è¡¨ç¤º `/` ç®å½ã
> [!info] ç¸å
³é¾æ¥
>
> * [javaè·åæä»¶è·¯å¾æ»ç»\_inputstreamè·åæä»¶è·¯å¾-CSDNå客](https://blog.csdn.net/qq_38747892/article/details/126751734)
> * [Javaä¸çgetResource()æ¹æ³ï¼åè·¯å¾ç¸å
³é®é¢](https://cloud.tencent.com/developer/article/1901321)
### éå
File ç±»ä¸æä¸¤ç»æ¹æ³ï¼`list()` å `listFiles()` ç¨æ¥éåã
`list()` çè¿å弿¯å符串æ°ç»ï¼å³æä»¶æç®å½çåç§°ã
`listFiles()` çè¿å弿¯ File ç±»åçæ°ç»ï¼å³è¿åçæ¯ File ç对象ã
è¿ä¸¤ç»æ¹æ³çéè½½æ¹æ³ï¼é½è½æ¥æ¶ [FileFilter](#javaio_io_filter_filefilter) å [FilenameFilter](#javaio_io_filter_filenamefilter) è¿ä¸¤ç§ [è¿æ»¤å¨](#javaio_io_filter)ã
### è¿æ»¤å¨
#### FilterInputStream
`FilterInputStream` æ¯ææè¿æ»¤è¾å
¥æµçææç±»çç¶ç±»ã
è§å¯ [InputStream ç±»å¾](#InputStream%20ç±»å¾)ï¼åç° `FilterInputStream` çæé æ¹æ³æ¯ `protected` çãä¹å°±æ¯è¯´é¤äºå
¶èªèº«è¿æååç±»å¤çç¬¬ä¸æ¹è¦å建å®ï¼æ¯ä¸è½éè¿ `new FilterInputStream()` æ¥å建çï¼åªè½éè¿å
¶åç±»ï¼å¦ [BufferedInputStream](#åèç¼å²æµ) çåç±»æ¥å建ã
#### FilterOutputStream
`FilterOutputStream` æ¯ææè¿æ»¤è¾åºæµçææç±»çç¶ç±»ã
#### FileFilter
FileFilter æä»¶è¿æ»¤å¨ã
å¨ [JDK8](#JDK8) åï¼FileFilter æ¥å£è¢«æ 记为 [彿°å¼æ¥å£](#彿°å¼æ¥å£)ï¼æä»¥å¯ä»¥ä½¿ç¨ [Lambda](Java_Note.md#java_lambda) è¯æ³å»å¿«éå®ç°è¿ä¸ªæ¥å£ã
FileFilter æ¥å£åªæä¸ä¸ªæ¹æ³ï¼`boolean accept(File pathname)`ãåæ°åªæä¸ä¸ªï¼å³ä¼ å
¥ä¸ä¸ªè¦è¿æ»¤çç®å½ File 对象ã
> [!example] 示ä¾
>
> ```java
> public class File_E03 {
>
> static Logger logger = Logger.getLogger("File_E03");
>
> public static void main(String[] args) {
>
> try {
>
> // å½åç±»æå¨çç®å½
> File dir01 = new File(File_E03.class.getResource("").getPath());
>
> // è·åææjavaæä»¶
> // listFiles() æ¹æ³å¾å°çæ¯Fileçæ°ç»
> File[] files = dir01.listFiles((f) -> f.getPath().endsWith(".java"));
>
> // éå
> for (File f_temp : files) {
> System.out.println("æä»¶åï¼" + f_temp.getName());
> System.out.println("æä»¶ç»å¯¹è·¯å¾ï¼" + f_temp.getAbsolutePath());
> System.out.println("æä»¶è·¯å¾ï¼" + f_temp.getPath());
>
> System.out.println("---------------------------------------");
> }
>
> } catch (NullPointerException e) {
>
> logger.severe(e.getMessage());
>
> }
>
> }
> }
>
>
> ```
>
#### FilenameFilter
FilenameFilter æä»¶åè¿æ»¤å¨ã
å¨ [JDK8](Java_Note.md#JDK8) åï¼FilenameFilter æ¥å£è¢«æ 记为 [彿°å¼æ¥å£](Java_Note.md#彿°å¼æ¥å£)ï¼æä»¥å¯ä»¥ä½¿ç¨ [Lambda](Java_Note.md#java_lambda) è¯æ³å»å¿«éå®ç°è¿ä¸ªæ¥å£ã
è¿æ¥å£æä¸åªæä¸ä¸ªæ¹æ³ï¼`accept(File dir, String name)`ã
> [!example] ååºæç®å½ä¸ææ java æä»¶
>
> ```java
> public class File_E02 {
>
> static Logger logger = Logger.getLogger("File_E02");
>
> public static void main(String[] args) {
>
> try {
>
>
> // å½åç±»æå¨ç®å½
> File f01 = new File(File_E02.class.getResource("").getPath());
>
> // ååºæ¤ç®å½ä¸ææåç¼å为".java"çæä»¶
> String[] files = f01.list((dir, fname) -> {
> return fname.endsWith(".java");
> });
>
> // éåæä»¶åæ°ç»
> for (String fn_temp : files) {
>
> File f = new File(f01, fn_temp);
>
> if (f.isFile()) {
> System.out.println("æä»¶åï¼" + f.getName());
> System.out.println("æä»¶ç»å¯¹è·¯å¾ï¼" + f.getAbsolutePath());
> System.out.println("æä»¶è·¯å¾ï¼" + f.getPath());
> } else {
> System.out.println("åç®å½ï¼" + f);
> }
> System.out.println("-----------------------------");
> }
>
> } catch (NullPointerException e) {
>
> logger.severe(e.getMessage());
> }
>
> }
>
> }
>
> ```
> å 为 FilenameFilter æ¥å£å·²ç»è¢«æ è®°ä¸ºå½æ°å¼æ¥å£ï¼æä»¥ç¤ºä¾ä»£ç ä¸ä½¿ç¨äº lambda æ¥å®ä¹è¿æ¥å£çå®ç°ã
>
### åèæµ
#### 常ç¨ç¤ºä¾
```java
package io_exercise;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
public class IO_E01 {
public static void main(String[] args) {
try (InputStream inputStr = new FileInputStream(
// è·åè¦è¯»åçæä»¶
IO_E01.class.getResource("t01.txt").getPath())) {
// ç¨æ¥è£
æ¯æ¬¡è¯»åå°çå符
// å符æ°ç»å¤§å°å³å®æ¯æ¬¡è¯»äºå¤å°å符
var bbuf = new byte[1024];
// å®é
读åçå符æ°
var hasRead = 0;
while ((hasRead = inputStr.read(bbuf)) > 0) {
System.out.println(new String(bbuf, 0, hasRead));
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
```
> [!tip] å
³éæµ
>
> å¨ [JDK1.7ï¼å³JDK7ï¼](Java_Note#JDK) ä¹åççæ¬ï¼éè¦æå¨å
³éæµï¼æä»¥å¸¸å¸¸å¨ `finally` 代ç å䏿§è¡ `inputStr.close()` ç代ç ã
>
> ä½ä» 1.7 å¼å§ï¼æµæ¥å£å·²ç»å®ç°äº `AutoCloseable` æ¥å£ï¼é¡¾åæä¹ï¼io æµå·²ç»å¯ä»¥ãèªå¨ãå
³éäºï¼æ é¡»åæå¨åå
³éæµç代ç äºã
### FileInputStream
`FileInputStream` æ¯ [åèæµ](#javaio_io_bytestream) æ½è±¡ç±» `InputStream` çåç±»ã
#### FileInputStream ä¸ InputStream åºå«
`InputStream` æ¯åèæµçæ½è±¡åºç±»ï¼å®å¯ä»¥ä»ä»»æçæ°æ®æºä¸è¯»ååèæ°æ®ï¼å
æ¬å
åãç½ç»ãæä»¶çï¼
`FileInputStream` 顾åæä¹ï¼å®åªè½ä»æä»¶è¯»ååèæ°æ®ã
对æ¯ä¸ä¸¤è
é¨åæºç 对æ¯ï¼
--- start-multi-column:
```column-settings
Number of Columns: 2
Largest Column: standard
```
FileInputStream
```java
private native int readBytes(byte[] b, int off, int len) throws IOException;
@Override
public int read(byte[] b) throws IOException {
long comp = Blocker.begin();
try {
return readBytes(b, 0, b.length);
} finally {
Blocker.end(comp);
}
}
```
--- end-column ---
InputStream
```java
public int read(byte[] b) throws IOException {
return read(b, 0, b.length);
}
```
--- end-multi-column
å¯åç°ï¼`FileInputStream` ç `read(byte[] b)` æ¹æ³è°äºä¸ä¸ª native æ¹æ³
### FileOutputStream
`FileOutputStream` æ¯è¾éè¦çæ¹æ³ï¼`write(byte[] b, int off, int len)`ã
#### FileInputStream å FileOutputStream 示ä¾
```java
public class File_E05 {
static Logger logger = Logger.getLogger("File_E05");
public static void main(String[] args) {
// è¦è¯»åçæä»¶
File fin = new File(File_E05.class.getResource("t01.txt").getPath());
// è¦è¾åºçæä»¶
File fout = new File(File_E05.class.getResource("").getPath() +
File.separator + "t01_backup.txt");
try (FileInputStream fis = new FileInputStream(fin);
FileOutputStream fos = new FileOutputStream(fout)) {
byte[] buffer = new byte[10];
int len = 0;
while ((len = fis.read(buffer)) > 0) {
String cpStr = new String(buffer);
// æå°ä¸
System.out.print(cpStr);
// ååº
fos.write(buffer, 0, len);
}
} catch (FileNotFoundException fnfe) {
logger.severe(fnfe.getMessage());
} catch (IOException ioe) {
logger.severe(ioe.getMessage());
} catch (NullPointerException npe) {
logger.severe(npe.getMessage());
} catch (Exception e) {
logger.severe(e.getMessage());
}
}
}
```
### åèç¼å²æµ
`BufferedInputStream` ä¸ `BufferedOutputStream` 称为åèç¼å²æµã使ç¨å
ç½®çç¼å²åºå¯¹è¯»åæè¾åºçæ°æ®è¿è¡ç¼å²ï¼ä»¥æ¤åå°ç´æ¥è¯»åæ°æ®æºç次æ°ã
`BufferedInputStream` å `BufferedOutputStream` æ¯ [FilterInputStream](#javaio_io_filter_filterinputstream) ä¸ [FilterOutputStream](#javaio_io_filter_filteroutputstream) çåç±»ã
åèç¼å²æµé»è®¤çç¼å²åºå¤§å°æ¯**8M**ãè¿ä¸ªæ°å¼å¯è½éè¿éè½½çæé æ¹æ³è¿è¡è®¾ç½®ï¼`public BufferedInputStream(InputStream in, int size)`ãè¿ä¸ªæ°å¼æå¥½æ¯ 2 ç n 次å¹ã
> [!info] BufferedInputStream æºç
>
> `private static final int DEFAULT_BUFFER_SIZE = 8192;`
è¿ä¸¤ç±»å¨å¯¹è±¡å®ä¾åæ¶ï¼éè¦ä¼ å
¥ [FileInputStream](#javaio_io_bytestream_fileinputstream) å [FileOutputStream](#javaio_io_bytestream_fileouputstream) å®ä¾å¯¹è±¡ã
èå
¶ `read()` æ¹æ³ä¸ `write()` æ¹æ³ç¨æ³ä¸ `FileInputStream` ä¸ `FileOutputStream` 大åå°å¼ã
#### BufferedInputStream ä¸ BufferedOutputStream 示ä¾
```java
// ç±»æå¨çç®å½è·¯å¾
String current_path = File_E06.class.getResource("").getPath();
// è¦è¯»åçæä»¶
File in_file = new File(current_path +
File.separator + "t01.txt");
// è¦è¾åºçæä»¶
File out_file = new File(current_path +
File.separator + "t01_backup.txt");
// è¯»åæ°æ®åèç¼å
byte[] buff = new byte[64];
int len = 0;
try (FileInputStream fis = new FileInputStream(in_file);
BufferedInputStream bis = new BufferedInputStream(fis);
FileOutputStream fos = new FileOutputStream(out_file);
BufferedOutputStream bos = new BufferedOutputStream(fos)) {
// 读å
while ((len = bis.read(buff)) > 0) {
// è¾åº
bos.write(buff, 0, len);
}
```
---
## NIO
`java.nio` æ¯ [JDK 1.4](Java_Note.md#JDK) å°±å·²ç»æä¾çã
### Buffer
`Buffer` æ¯ [NIO](#javaio_nio) çæ ¸å¿ãnio ç API 齿¯å´ç»ç `Buffer` è设计çã
```mermaid
classDiagram
Buffer <|-- ByteBuffer
class Buffer{
<>
+position() int
+position(int newPosition) Buffer
+limit() int
+limit(int newLimit) Buffer
+flip() Buffer
+remaining() int
+capacity() int
+clear() Buffer
+hasRemaining() boolean
+slice() Buffer
+slice(int index, int length) Buffer
+mark() Buffer
+isDirect() boolean
+isReadOnly() boolean
}
class ByteBuffer{
<>
+allocate(int capacity) ByteBuffer
+allocateDirect(int capacity) ByteBuffer
+get() bype
+get(byte[] dst) ByteBuffer
+get(byte[] dst, int offset, int length) ByteBuffer
+get(int index) bype
+get(int index, bype[] dst) ByteBuffer
+get(int index, byte[] dst, int offset, int length) ByteBuffer
+getChar() char
+getChar(int index) char
+getDouble() double
+getDouble(int index) double
+getFloat() float
+getFloat(int index) float
+getInt() int
+getInt(int index) int
+getLong() long
+getLong(int index) long
+put(byte b) ByteBuffer
+put(byte[] src) ByteBuffer
+put(byte[] src, int offset, int length) ByteBuffer
+put(int value) ByteBuffer
+put(int index, int value) ByteBuffer
}
```
---
## ç¸å
³ç¬è®°
* [Java ç¬è®°](Java_Note.md)
* [Java åºç¡ç¬è®°](Java_Base_Note.md)
* [Java è§é¢æ¸
å](Java_Videos.md)