diff --git a/notes/Java IO.md b/notes/Java IO.md
index 1e3aedcd..a14ea902 100644
--- a/notes/Java IO.md
+++ b/notes/Java IO.md
@@ -2,8 +2,17 @@
* [一、概览](#一概览)
* [二、磁盘操作](#二磁盘操作)
* [三、字节操作](#三字节操作)
+ * [实现文件复制](#实现文件复制)
+ * [装饰者模式](#装饰者模式)
* [四、字符操作](#四字符操作)
+ * [编码与解码](#编码与解码)
+ * [String](#string)
+ * [Reader 与 Writer](#reader-与-writer)
+ * [实现逐行输出文本文件的内容](#实现逐行输出文本文件的内容)
* [五、对象操作](#五对象操作)
+ * [序列化](#序列化)
+ * [Serializable](#serializable)
+ * [transient](#transient)
* [六、网络操作](#六网络操作)
* [InetAddress](#inetaddress)
* [URL](#url)
@@ -37,7 +46,7 @@ Java 的 I/O 大概可以分成以下几类:
File 类可以用于表示文件和目录的信息,但是它不表示文件的内容。
-递归地输出一个目录下所有文件:
+递归地列出一个目录下所有文件:
```java
public static void listAllFiles(File dir) {
@@ -56,7 +65,7 @@ public static void listAllFiles(File dir) {
# 三、字节操作
-使用字节流操作进行文件复制:
+## 实现文件复制
```java
public static void copyFile(String src, String dist) throws IOException {
@@ -77,13 +86,15 @@ public static void copyFile(String src, String dist) throws IOException {
}
```
-
+## 装饰者模式
Java I/O 使用了装饰者模式来实现。以 InputStream 为例,
- InputStream 是抽象组件;
- FileInputStream 是 InputStream 的子类,属于具体组件,提供了字节流的输入操作;
-- FilterInputStream 属于抽象装饰者,装饰者用于装饰组件,为组件提供额外的功能,例如 BufferedInputStream 为 FileInputStream 提供缓存的功能。
+- FilterInputStream 属于抽象装饰者,装饰者用于装饰组件,为组件提供额外的功能。例如 BufferedInputStream 为 FileInputStream 提供缓存的功能。
+
+
实例化一个具有缓存功能的字节流对象时,只需要在 FileInputStream 对象上再套一层 BufferedInputStream 对象即可。
@@ -96,27 +107,7 @@ DataInputStream 装饰者提供了对更多数据类型进行输入的操作,
# 四、字符操作
-不管是磁盘还是网络传输,最小的存储单元都是字节,而不是字符。但是在程序中操作的通常是字符形式的数据,因此需要提供对字符进行操作的方法。
-
-- InputStreamReader 实现从字节流解码成字符流;
-- OutputStreamWriter 实现字符流编码成为字节流。
-
-逐行输出文本文件的内容:
-
-```java
-public static void readFileContent(String filePath) throws IOException {
- FileReader fileReader = new FileReader(filePath);
- BufferedReader bufferedReader = new BufferedReader(fileReader);
- String line;
- while ((line = bufferedReader.readLine()) != null) {
- System.out.println(line);
- }
- // 装饰者模式使得 BufferedReader 组合了一个 Reader 对象
- // 在调用 BufferedReader 的 close() 方法时会去调用 fileReader 的 close() 方法
- // 因此只要一个 close() 调用即可
- bufferedReader.close();
-}
-```
+## 编码与解码
编码就是把字符转换为字节,而解码是把字节重新组合成字符。
@@ -130,6 +121,8 @@ UTF-16be 中的 be 指的是 Big Endian,也就是大端。相应地也有 UTF-
Java 使用双字节编码 UTF-16be,这不是指 Java 只支持这一种编码方式,而是说 char 这种类型使用 UTF-16be 进行编码。char 类型占 16 位,也就是两个字节,Java 使用这种双字节编码是为了让一个中文或者一个英文都能使用一个 char 来存储。
+## String
+
String 可以看成一个字符序列,可以指定一个编码方式将它编码为字节序列,也可以指定一个编码方式将一个字节序列解码为 String。
```java
@@ -145,13 +138,46 @@ System.out.println(str2);
byte[] bytes = str1.getBytes();
```
+## Reader 与 Writer
+
+不管是磁盘还是网络传输,最小的存储单元都是字节,而不是字符。但是在程序中操作的通常是字符形式的数据,因此需要提供对字符进行操作的方法。
+
+- InputStreamReader 实现从字节流解码成字符流;
+- OutputStreamWriter 实现字符流编码成为字节流。
+
+## 实现逐行输出文本文件的内容
+
+```java
+public static void readFileContent(String filePath) throws IOException {
+
+ FileReader fileReader = new FileReader(filePath);
+ BufferedReader bufferedReader = new BufferedReader(fileReader);
+
+ String line;
+ while ((line = bufferedReader.readLine()) != null) {
+ System.out.println(line);
+ }
+
+ // 装饰者模式使得 BufferedReader 组合了一个 Reader 对象
+ // 在调用 BufferedReader 的 close() 方法时会去调用 Reader 的 close() 方法
+ // 因此只要一个 close() 调用即可
+ bufferedReader.close();
+}
+```
+
# 五、对象操作
+## 序列化
+
序列化就是将一个对象转换成字节序列,方便存储和传输。
- 序列化:ObjectOutputStream.writeObject()
- 反序列化:ObjectInputStream.readObject()
+不会对静态变量进行序列化,因为序列化只是保存对象的状态,静态变量属于类的状态。
+
+## Serializable
+
序列化的类需要实现 Serializable 接口,它只是一个标准,没有任何方法需要实现,但是如果不去实现它的话而进行序列化,会抛出异常。
```java
@@ -184,11 +210,11 @@ private static class A implements Serializable {
}
```
-不会对静态变量进行序列化,因为序列化只是保存对象的状态,静态变量属于类的状态。
+## transient
transient 关键字可以使一些属性不会被序列化。
-ArrayList 中存储数据的数组是用 transient 修饰的,因为这个数组是动态扩展的,并不是所有的空间都被使用,因此就不需要所有的内容都被序列化。通过重写序列化和反序列化方法,使得可以只序列化数组中有内容的那部分数据。
+ArrayList 中存储数据的数组 elementData 是用 transient 修饰的,因为这个数组是动态扩展的,并不是所有的空间都被使用,因此就不需要所有的内容都被序列化。通过重写序列化和反序列化方法,使得可以只序列化数组中有内容的那部分数据。
```java
private transient Object[] elementData;
@@ -249,8 +275,8 @@ public static void main(String[] args) throws IOException {
## Datagram
-- DatagramPacket:数据包类
- DatagramSocket:通信类
+- DatagramPacket:数据包类
# 七、NIO