From eace8369dd11d548c5a57491bbeee4d439ef18bb Mon Sep 17 00:00:00 2001
From: CyC2018 <1029579233@qq.com>
Date: Sun, 5 Aug 2018 16:35:58 +0800
Subject: [PATCH] auto commit
---
notes/Java IO.md | 123 ++++++++++++++++++++++++++++++-----------------
1 file changed, 80 insertions(+), 43 deletions(-)
diff --git a/notes/Java IO.md b/notes/Java IO.md
index 08dc80f4..d93ff47c 100644
--- a/notes/Java IO.md
+++ b/notes/Java IO.md
@@ -40,8 +40,7 @@ File 类可以用于表示文件和目录的信息,但是它不表示文件的
递归地输出一个目录下所有文件:
```java
-public static void listAllFiles(File dir)
-{
+public static void listAllFiles(File dir) {
if (dir == null || !dir.exists()) {
return;
}
@@ -60,8 +59,7 @@ public static void listAllFiles(File dir)
使用字节流操作进行文件复制:
```java
-public static void copyFile(String src, String dist) throws IOException
-{
+public static void copyFile(String src, String dist) throws IOException {
FileInputStream in = new FileInputStream(src);
FileOutputStream out = new FileOutputStream(dist);
byte[] buffer = new byte[20 * 1024];
@@ -78,7 +76,11 @@ public static void copyFile(String src, String dist) throws IOException
-Java I/O 使用了装饰者模式来实现。以 InputStream 为例,InputStream 是抽象组件,FileInputStream 是 InputStream 的子类,属于具体组件,提供了字节流的输入操作。FilterInputStream 属于抽象装饰者,装饰者用于装饰组件,为组件提供额外的功能,例如 BufferedInputStream 为 FileInputStream 提供缓存的功能。
+Java I/O 使用了装饰者模式来实现。以 InputStream 为例,
+
+- InputStream 是抽象组件;
+- FileInputStream 是 InputStream 的子类,属于具体组件,提供了字节流的输入操作;
+- FilterInputStream 属于抽象装饰者,装饰者用于装饰组件,为组件提供额外的功能,例如 BufferedInputStream 为 FileInputStream 提供缓存的功能。
实例化一个具有缓存功能的字节流对象时,只需要在 FileInputStream 对象上再套一层 BufferedInputStream 对象即可。
@@ -99,8 +101,7 @@ DataInputStream 装饰者提供了对更多数据类型进行输入的操作,
逐行输出文本文件的内容:
```java
-public static void readFileContent(String filePath) throws IOException
-{
+public static void readFileContent(String filePath) throws IOException {
FileReader fileReader = new FileReader(filePath);
BufferedReader bufferedReader = new BufferedReader(fileReader);
String line;
@@ -126,7 +127,7 @@ UTF-16be 中的 be 指的是 Big Endian,也就是大端。相应地也有 UTF-
Java 使用双字节编码 UTF-16be,这不是指 Java 只支持这一种编码方式,而是说 char 这种类型使用 UTF-16be 进行编码。char 类型占 16 位,也就是两个字节,Java 使用这种双字节编码是为了让一个中文或者一个英文都能使用一个 char 来存储。
-String 可以看成一个字符序列,可以指定一个编码方式将它转换为字节序列,也可以指定一个编码方式将一个字节序列转换为 String。
+String 可以看成一个字符序列,可以指定一个编码方式将它编码为字节序列,也可以指定一个编码方式将一个字节序列解码为 String。
```java
String str1 = "中文";
@@ -151,8 +152,7 @@ byte[] bytes = str1.getBytes();
序列化的类需要实现 Serializable 接口,它只是一个标准,没有任何方法需要实现,但是如果不去实现它的话而进行序列化,会抛出异常。
```java
-public static void main(String[] args) throws IOException, ClassNotFoundException
-{
+public static void main(String[] args) throws IOException, ClassNotFoundException {
A a1 = new A(123, "abc");
String objectFile = "file/a1";
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream(objectFile));
@@ -188,7 +188,7 @@ private static class A implements Serializable
transient 关键字可以使一些属性不会被序列化。
-**ArrayList 序列化和反序列化的实现** :ArrayList 中存储数据的数组是用 transient 修饰的,因为这个数组是动态扩展的,并不是所有的空间都被使用,因此就不需要所有的内容都被序列化。通过重写序列化和反序列化方法,使得可以只序列化数组中有内容的那部分数据。
+ArrayList 中存储数据的数组是用 transient 修饰的,因为这个数组是动态扩展的,并不是所有的空间都被使用,因此就不需要所有的内容都被序列化。通过重写序列化和反序列化方法,使得可以只序列化数组中有内容的那部分数据。
```java
private transient Object[] elementData;
@@ -205,7 +205,7 @@ Java 中的网络支持:
## InetAddress
-没有公有构造函数,只能通过静态方法来创建实例。
+没有公有的构造函数,只能通过静态方法来创建实例。
```java
InetAddress.getByName(String host);
@@ -217,19 +217,24 @@ InetAddress.getByAddress(byte[] address);
可以直接从 URL 中读取字节流数据。
```java
-public static void main(String[] args) throws IOException
-{
+public static void main(String[] args) throws IOException {
+
URL url = new URL("http://www.baidu.com");
- // 字节流
+
+ /* 字节流 */
InputStream is = url.openStream();
- // 字符流
+
+ /* 字符流 */
InputStreamReader isr = new InputStreamReader(is, "utf-8");
+
+ /* 提供缓存功能 */
BufferedReader br = new BufferedReader(isr);
- String line = br.readLine();
- while (line != null) {
+
+ String line;
+ while ((line = br.readLine()) != null) {
System.out.println(line);
- line = br.readLine();
}
+
br.close();
}
```
@@ -253,7 +258,7 @@ public static void main(String[] args) throws IOException
- [Java NIO 浅析](https://tech.meituan.com/nio.html)
- [IBM: NIO 入门](https://www.ibm.com/developerworks/cn/education/java/j-nio/j-nio.html)
-新的输入/输出 (NIO) 库是在 JDK 1.4 中引入的。NIO 弥补了原来的 I/O 的不足,提供了高速的、面向块的 I/O。
+新的输入/输出 (NIO) 库是在 JDK 1.4 中引入的,弥补了原来的 I/O 的不足,提供了高速的、面向块的 I/O。
## 流与块
@@ -271,7 +276,7 @@ I/O 包和 NIO 已经很好地集成了,java.io.\* 已经以 NIO 为基础重
通道 Channel 是对原 I/O 包中的流的模拟,可以通过它读取和写入数据。
-通道与流的不同之处在于,流只能在一个方向上移动,(一个流必须是 InputStream 或者 OutputStream 的子类),而通道是双向的,可以用于读、写或者同时用于读写。
+通道与流的不同之处在于,流只能在一个方向上移动(一个流必须是 InputStream 或者 OutputStream 的子类),而通道是双向的,可以用于读、写或者同时用于读写。
通道包括以下类型:
@@ -329,21 +334,41 @@ I/O 包和 NIO 已经很好地集成了,java.io.\* 已经以 NIO 为基础重
以下展示了使用 NIO 快速复制文件的实例:
```java
-public static void fastCopy(String src, String dist) throws IOException
-{
- FileInputStream fin = new FileInputStream(src); /* 获取源文件的输入字节流 */
- FileChannel fcin = fin.getChannel(); /* 获取输入字节流的文件通道 */
- FileOutputStream fout = new FileOutputStream(dist); /* 获取目标文件的输出字节流 */
- FileChannel fcout = fout.getChannel(); /* 获取输出字节流的通道 */
- ByteBuffer buffer = ByteBuffer.allocateDirect(1024); /* 为缓冲区分配 1024 个字节 */
+public static void fastCopy(String src, String dist) throws IOException {
+
+ /* 获得源文件的输入字节流 */
+ FileInputStream fin = new FileInputStream(src);
+
+ /* 获取输入字节流的文件通道 */
+ FileChannel fcin = fin.getChannel();
+
+ /* 获取目标文件的输出字节流 */
+ FileOutputStream fout = new FileOutputStream(dist);
+
+ /* 获取输出字节流的通道 */
+ FileChannel fcout = fout.getChannel();
+
+ /* 为缓冲区分配 1024 个字节 */
+ ByteBuffer buffer = ByteBuffer.allocateDirect(1024);
+
while (true) {
- int r = fcin.read(buffer); /* 从输入通道中读取数据到缓冲区中 */
- if (r == -1) { /* read() 返回 -1 表示 EOF */
+
+ /* 从输入通道中读取数据到缓冲区中 */
+ int r = fcin.read(buffer);
+
+ /* read() 返回 -1 表示 EOF */
+ if (r == -1) {
break;
}
- buffer.flip(); /* 切换读写 */
- fcout.write(buffer); /* 把缓冲区的内容写入输出文件中 */
- buffer.clear(); /* 清空缓冲区 */
+
+ /* 切换读写 */
+ buffer.flip();
+
+ /* 把缓冲区的内容写入输出文件中 */
+ fcout.write(buffer);
+
+ /* 清空缓冲区 */
+ buffer.clear();
}
}
```
@@ -448,10 +473,10 @@ while (true) {
## 套接字 NIO 实例
```java
-public class NIOServer
-{
- public static void main(String[] args) throws IOException
- {
+public class NIOServer {
+
+ public static void main(String[] args) throws IOException {
+
Selector selector = Selector.open();
ServerSocketChannel ssChannel = ServerSocketChannel.open();
@@ -463,32 +488,45 @@ public class NIOServer
serverSocket.bind(address);
while (true) {
+
selector.select();
Set keys = selector.selectedKeys();
Iterator keyIterator = keys.iterator();
+
while (keyIterator.hasNext()) {
+
SelectionKey key = keyIterator.next();
+
if (key.isAcceptable()) {
+
ServerSocketChannel ssChannel1 = (ServerSocketChannel) key.channel();
+
// 服务器会为每个新连接创建一个 SocketChannel
SocketChannel sChannel = ssChannel1.accept();
sChannel.configureBlocking(false);
+
// 这个新连接主要用于从客户端读取数据
sChannel.register(selector, SelectionKey.OP_READ);
+
} else if (key.isReadable()) {
+
SocketChannel sChannel = (SocketChannel) key.channel();
System.out.println(readDataFromSocketChannel(sChannel));
sChannel.close();
}
+
keyIterator.remove();
}
}
}
private static String readDataFromSocketChannel(SocketChannel sChannel) throws IOException {
+
ByteBuffer buffer = ByteBuffer.allocate(1024);
StringBuilder data = new StringBuilder();
+
while (true) {
+
buffer.clear();
int n = sChannel.read(buffer);
if (n == -1) {
@@ -509,10 +547,9 @@ public class NIOServer
```
```java
-public class NIOClient
-{
- public static void main(String[] args) throws IOException
- {
+public class NIOClient {
+
+ public static void main(String[] args) throws IOException {
Socket socket = new Socket("127.0.0.1", 8888);
OutputStream out = socket.getOutputStream();
String s = "hello world";
@@ -526,9 +563,9 @@ public class NIOClient
内存映射文件 I/O 是一种读和写文件数据的方法,它可以比常规的基于流或者基于通道的 I/O 快得多。
-向内存映射文件写入可能是危险的,仅只是改变数组的单个元素这样的简单操作,就可能会直接修改磁盘上的文件。修改数据与将数据保存到磁盘是没有分开的。
+向内存映射文件写入可能是危险的,只是改变数组的单个元素这样的简单操作,就可能会直接修改磁盘上的文件。修改数据与将数据保存到磁盘是没有分开的。
-下面代码行将文件的前 1024 个字节映射到内存中,map() 方法返回一个 MappedByteBuffer,它是 ByteBuffer 的子类。因此,您可以像使用其他任何 ByteBuffer 一样使用新映射的缓冲区,操作系统会在需要时负责执行映射。
+下面代码行将文件的前 1024 个字节映射到内存中,map() 方法返回一个 MappedByteBuffer,它是 ByteBuffer 的子类。因此,可以像使用其他任何 ByteBuffer 一样使用新映射的缓冲区,操作系统会在需要时负责执行映射。
```java
MappedByteBuffer mbb = fc.map(FileChannel.MapMode.READ_WRITE, 0, 1024);
--
GitLab