Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
wushizhenking
CS-Notes
提交
eace8369
C
CS-Notes
项目概览
wushizhenking
/
CS-Notes
与 Fork 源项目一致
从无法访问的项目Fork
通知
2
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
C
CS-Notes
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
eace8369
编写于
8月 05, 2018
作者:
C
CyC2018
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
auto commit
上级
cc527754
变更
1
隐藏空白更改
内联
并排
Showing
1 changed file
with
80 addition
and
43 deletion
+80
-43
notes/Java IO.md
notes/Java IO.md
+80
-43
未找到文件。
notes/Java IO.md
浏览文件 @
eace8369
...
...
@@ -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.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录