auto commit

This commit is contained in:
CyC2018
2020-11-17 00:32:18 +08:00
parent f5ad47b470
commit 7e61fc1360
380 changed files with 2371 additions and 46715 deletions

View File

@@ -1,37 +1,18 @@
# Java IO
<!-- GFM-TOC -->
* [一、概览](#一概览)
* [二、磁盘操作](#二磁盘操作)
* [三、字节操作](#三字节操作)
* [实现文件复制](#实现文件复制)
* [装饰者模式](#装饰者模式)
* [四、字符操作](#四字符操作)
* [编码与解码](#编码与解码)
* [String 的编码方式](#string-的编码方式)
* [Reader 与 Writer](#reader-与-writer)
* [实现逐行输出文本文件的内容](#实现逐行输出文本文件的内容)
* [五、对象操作](#五对象操作)
* [序列化](#序列化)
* [Serializable](#serializable)
* [transient](#transient)
* [六、网络操作](#六网络操作)
* [InetAddress](#inetaddress)
* [URL](#url)
* [Sockets](#sockets)
* [Datagram](#datagram)
* [七、NIO](#七nio)
* [流与块](#流与块)
* [通道与缓冲区](#通道与缓冲区)
* [缓冲区状态变量](#缓冲区状态变量)
* [文件 NIO 实例](#文件-nio-实例)
* [选择器](#选择器)
* [套接字 NIO 实例](#套接字-nio-实例)
* [内存映射文件](#内存映射文件)
* [对比](#对比)
* [八、参考资料](#八参考资料)
* [Java IO](#java-io)
* [一、概览](#一概览)
* [二、磁盘操作](#二磁盘操作)
* [三、字节操作](#三字节操作)
* [四、字符操作](#四字符操作)
* [五、对象操作](#五对象操作)
* [六、网络操作](#六网络操作)
* [七、NIO](#七nio)
* [八、参考资料](#八参考资料)
<!-- GFM-TOC -->
# 一、概览
## 一、概览
Java 的 I/O 大概可以分成以下几类:
@@ -42,7 +23,7 @@ Java 的 I/O 大概可以分成以下几类:
- 网络操作:Socket
- 新的输入/输出:NIO
# 二、磁盘操作
## 二、磁盘操作
File 类可以用于表示文件和目录的信息,但是它不表示文件的内容。
@@ -65,9 +46,9 @@ public static void listAllFiles(File dir) {
从 Java7 开始,可以使用 Paths 和 Files 代替 File。
# 三、字节操作
## 三、字节操作
## 实现文件复制
### 实现文件复制
```java
public static void copyFile(String src, String dist) throws IOException {
@@ -89,7 +70,7 @@ public static void copyFile(String src, String dist) throws IOException {
}
```
## 装饰者模式
### 装饰者模式
Java I/O 使用了装饰者模式来实现。以 InputStream 为例,
@@ -108,9 +89,9 @@ BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStrea
DataInputStream 装饰者提供了对更多数据类型进行输入的操作,比如 int、double 等基本类型。
# 四、字符操作
## 四、字符操作
## 编码与解码
### 编码与解码
编码就是把字符转换为字节,而解码是把字节重新组合成字符。
@@ -124,7 +105,7 @@ UTF-16be 中的 be 指的是 Big Endian,也就是大端。相应地也有 UTF-
Java 的内存编码使用双字节编码 UTF-16be,这不是指 Java 只支持这一种编码方式,而是说 char 这种类型使用 UTF-16be 进行编码。char 类型占 16 位,也就是两个字节,Java 使用这种双字节编码是为了让一个中文或者一个英文都能使用一个 char 来存储。
## String 的编码方式
### String 的编码方式
String 可以看成一个字符序列,可以指定一个编码方式将它编码为字节序列,也可以指定一个编码方式将一个字节序列解码为 String。
@@ -141,14 +122,14 @@ System.out.println(str2);
byte[] bytes = str1.getBytes();
```
## Reader 与 Writer
### Reader 与 Writer
不管是磁盘还是网络传输,最小的存储单元都是字节,而不是字符。但是在程序中操作的通常是字符形式的数据,因此需要提供对字符进行操作的方法。
- InputStreamReader 实现从字节流解码成字符流;
- OutputStreamWriter 实现字符流编码成为字节流。
## 实现逐行输出文本文件的内容
### 实现逐行输出文本文件的内容
```java
public static void readFileContent(String filePath) throws IOException {
@@ -168,9 +149,9 @@ public static void readFileContent(String filePath) throws IOException {
}
```
# 五、对象操作
## 五、对象操作
## 序列化
### 序列化
序列化就是将一个对象转换成字节序列,方便存储和传输。
@@ -179,7 +160,7 @@ public static void readFileContent(String filePath) throws IOException {
不会对静态变量进行序列化,因为序列化只是保存对象的状态,静态变量属于类的状态。
## Serializable
### Serializable
序列化的类需要实现 Serializable 接口,它只是一个标准,没有任何方法需要实现,但是如果不去实现它的话而进行序列化,会抛出异常。
@@ -216,7 +197,7 @@ private static class A implements Serializable {
}
```
## transient
### transient
transient 关键字可以使一些属性不会被序列化。
@@ -226,7 +207,7 @@ ArrayList 中存储数据的数组 elementData 是用 transient 修饰的,因
private transient Object[] elementData;
```
# 六、网络操作
## 六、网络操作
Java 中的网络支持:
@@ -235,7 +216,7 @@ Java 中的网络支持:
- Sockets:使用 TCP 协议实现网络通信;
- Datagram:使用 UDP 协议实现网络通信。
## InetAddress
### InetAddress
没有公有的构造函数,只能通过静态方法来创建实例。
@@ -244,7 +225,7 @@ InetAddress.getByName(String host);
InetAddress.getByAddress(byte[] address);
```
## URL
### URL
可以直接从 URL 中读取字节流数据。
@@ -271,7 +252,7 @@ public static void main(String[] args) throws IOException {
}
```
## Sockets
### Sockets
- ServerSocket:服务器端类
- Socket:客户端类
@@ -279,16 +260,16 @@ public static void main(String[] args) throws IOException {
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/1e6affc4-18e5-4596-96ef-fb84c63bf88a.png" width="550px"> </div><br>
## Datagram
### Datagram
- DatagramSocket:通信类
- DatagramPacket:数据包类
# 七、NIO
## 七、NIO
新的输入/输出 (NIO) 库是在 JDK 1.4 中引入的,弥补了原来的 I/O 的不足,提供了高速的、面向块的 I/O。
## 流与块
### 流与块
I/O 与 NIO 最重要的区别是数据打包和传输的方式,I/O 以流的方式处理数据,而 NIO 以块的方式处理数据。
@@ -298,9 +279,9 @@ I/O 与 NIO 最重要的区别是数据打包和传输的方式,I/O 以流的
I/O 包和 NIO 已经很好地集成了,java.io.\* 已经以 NIO 为基础重新实现了,所以现在它可以利用 NIO 的一些特性。例如,java.io.\* 包中的一些类包含以块的形式读写数据的方法,这使得即使在面向流的系统中,处理速度也会更快。
## 通道与缓冲区
### 通道与缓冲区
### 1. 通道
#### 1. 通道
通道 Channel 是对原 I/O 包中的流的模拟,可以通过它读取和写入数据。
@@ -313,7 +294,7 @@ I/O 包和 NIO 已经很好地集成了,java.io.\* 已经以 NIO 为基础重
- SocketChannel:通过 TCP 读写网络中数据;
- ServerSocketChannel:可以监听新进来的 TCP 连接,对每一个新进来的连接都会创建一个 SocketChannel。
### 2. 缓冲区
#### 2. 缓冲区
发送给一个通道的所有数据都必须首先放到缓冲区中,同样地,从通道中读取的任何数据都要先读到缓冲区中。也就是说,不会直接对通道进行读写数据,而是要先经过缓冲区。
@@ -329,7 +310,7 @@ I/O 包和 NIO 已经很好地集成了,java.io.\* 已经以 NIO 为基础重
- FloatBuffer
- DoubleBuffer
## 缓冲区状态变量
### 缓冲区状态变量
- capacity:最大容量;
- position:当前已经读写的字节数;
@@ -357,7 +338,7 @@ I/O 包和 NIO 已经很好地集成了,java.io.\* 已经以 NIO 为基础重
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/67bf5487-c45d-49b6-b9c0-a058d8c68902.png"/> </div><br>
## 文件 NIO 实例
### 文件 NIO 实例
以下展示了使用 NIO 快速复制文件的实例:
@@ -401,7 +382,7 @@ public static void fastCopy(String src, String dist) throws IOException {
}
```
## 选择器
### 选择器
NIO 常常被叫做非阻塞 IO,主要是因为 NIO 在网络通信中的非阻塞特性被广泛使用。
@@ -415,13 +396,13 @@ NIO 实现了 IO 多路复用中的 Reactor 模型,一个线程 Thread 使用
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/093f9e57-429c-413a-83ee-c689ba596cef.png" width="350px"> </div><br>
### 1. 创建选择器
#### 1. 创建选择器
```java
Selector selector = Selector.open();
```
### 2. 将通道注册到选择器上
#### 2. 将通道注册到选择器上
```java
ServerSocketChannel ssChannel = ServerSocketChannel.open();
@@ -453,7 +434,7 @@ public static final int OP_ACCEPT = 1 << 4;
int interestSet = SelectionKey.OP_READ | SelectionKey.OP_WRITE;
```
### 3. 监听事件
#### 3. 监听事件
```java
int num = selector.select();
@@ -461,7 +442,7 @@ int num = selector.select();
使用 select() 来监听到达的事件,它会一直阻塞直到有至少一个事件到达。
### 4. 获取到达的事件
#### 4. 获取到达的事件
```java
Set<SelectionKey> keys = selector.selectedKeys();
@@ -477,7 +458,7 @@ while (keyIterator.hasNext()) {
}
```
### 5. 事件循环
#### 5. 事件循环
因为一次 select() 调用不能处理完所有的事件,并且服务器端有可能需要一直监听事件,因此服务器端处理事件的代码一般会放在一个死循环内。
@@ -498,7 +479,7 @@ while (true) {
}
```
## 套接字 NIO 实例
### 套接字 NIO 实例
```java
public class NIOServer {
@@ -587,7 +568,7 @@ public class NIOClient {
}
```
## 内存映射文件
### 内存映射文件
内存映射文件 I/O 是一种读和写文件数据的方法,它可以比常规的基于流或者基于通道的 I/O 快得多。
@@ -599,14 +580,14 @@ public class NIOClient {
MappedByteBuffer mbb = fc.map(FileChannel.MapMode.READ_WRITE, 0, 1024);
```
## 对比
### 对比
NIO 与普通 I/O 的区别主要有以下两点:
- NIO 是非阻塞的;
- NIO 面向块,I/O 面向流。
# 八、参考资料
## 八、参考资料
- Eckel B, 埃克尔, 昊鹏, 等. Java 编程思想 [M]. 机械工业出版社, 2002.
- [IBM: NIO 入门](https://www.ibm.com/developerworks/cn/education/java/j-nio/j-nio.html)
@@ -618,10 +599,3 @@ NIO 与普通 I/O 的区别主要有以下两点:
- [NIO 与传统 IO 的区别](http://blog.csdn.net/shimiso/article/details/24990499)
- [Decorator Design Pattern](http://stg-tud.github.io/sedc/Lecture/ws13-14/5.3-Decorator.html#mode=document)
- [Socket Multicast](http://labojava.blogspot.com/2012/12/socket-multicast.html)
<div align="center"><img width="320px" src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/githubio/公众号二维码-2.png"></img></div>