提交 eace8369 编写于 作者: C CyC2018

auto commit

上级 cc527754
......@@ -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
<div align="center"> <img src="../pics//DP-Decorator-java.io.png" width="500"/> </div><br>
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<SelectionKey> keys = selector.selectedKeys();
Iterator<SelectionKey> 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);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册