Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
沉默王二
Jmx Java
提交
06e804e4
J
Jmx Java
项目概览
沉默王二
/
Jmx Java
10 个月 前同步成功
通知
160
Star
18
Fork
2
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
J
Jmx Java
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
06e804e4
编写于
3月 31, 2023
作者:
沉默王二
💬
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
NIO
上级
f165de46
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
298 addition
and
81 deletion
+298
-81
docs/home.md
docs/home.md
+2
-1
docs/io/file-path.md
docs/io/file-path.md
+128
-16
docs/nio/why.md
docs/nio/why.md
+41
-50
二哥的 Java 进阶之路.md
二哥的 Java 进阶之路.md
+127
-14
未找到文件。
docs/home.md
浏览文件 @
06e804e4
...
...
@@ -228,10 +228,11 @@ head:
### Java NIO
-
[
为什么我们要使用 Java NIO?
](
nio/why.md
)
-
[
如何给女朋友解释什么是 BIO、NIO 和 AIO?
](
nio/BIONIOAIO.md
)
-
[
Java NIO 快速入门(buffer缓冲区、Channel管道、Selector选择器)
](
nio/rumen.md
)
-
[
一文彻底理解Java IO模型(阻塞IO非阻塞IO/IO多路复用)
](
nio/moxing.md
)
-
[
使用Java NIO完成网络通信
](
nio/network-connect.md
)
-
[
如何给女朋友解释什么是 BIO、NIO 和 AIO?
](
nio/BIONIOAIO.md
)
### 重要知识点
...
...
docs/io/file-path.md
浏览文件 @
06e804e4
...
...
@@ -12,7 +12,7 @@ head:
content
:
Java,Java SE,Java基础,Java教程,Java程序员进阶之路,Java进阶之路,Java入门,教程,Java IO,file,java文件,java目录,java文件增删改查,java file
---
# 7.2 关于File
# 7.2 关于
File
在 IO 操作中,文件的操作相对来说是比较复杂的,但也是使用频率最高的部分,我们几乎所有的项目中几乎都躺着一个叫做 FileUtil 或者 FileUtils 的工具类。那么 File 类可以说是其基石,我们必须得先来了解下。
...
...
@@ -83,13 +83,13 @@ File 的常用方法主要分为获取功能、获取绝对路径和相对路径
测试代码如下【注意测试以你自己的电脑文件夹为准】:
```
java
File
f
=
new
File
(
"/Users/username/aaa/bbb.java"
);
File
f
=
new
File
(
"/Users/username/aaa/bbb.java"
);
System
.
out
.
println
(
"文件绝对路径:"
+
f
.
getAbsolutePath
());
System
.
out
.
println
(
"文件构造路径:"
+
f
.
getPath
());
System
.
out
.
println
(
"文件名称:"
+
f
.
getName
());
System
.
out
.
println
(
"文件长度:"
+
f
.
length
()+
"字节"
);
File
f2
=
new
File
(
"/Users/username/aaa"
);
File
f2
=
new
File
(
"/Users/username/aaa"
);
System
.
out
.
println
(
"目录绝对路径:"
+
f2
.
getAbsolutePath
());
System
.
out
.
println
(
"目录构造路径:"
+
f2
.
getPath
());
System
.
out
.
println
(
"目录名称:"
+
f2
.
getName
());
...
...
@@ -109,7 +109,6 @@ System.out.println("目录长度:"+f2.length());
-
在 Windows 操作系统中,文件系统默认是不区分大小写的,即在文件系统中,文件名和路径的大小写可以混合使用。例如,"
`C:\Users\username\Documents\example.txt`
" 和 "
`C:\Users\Username\Documents\Example.txt`
" 表示的是同一个文件。但是,Windows 操作系统提供了一个区分大小写的选项,可以在格式化磁盘时选择启用,这样文件系统就会区分大小写。
-
在 macOS 和 Linux 等 Unix 系统中,文件系统默认是区分大小写的。例如,在 macOS 系统中,"
`/Users/username/Documents/example.txt`
" 和 "
`/Users/username/Documents/Example.txt`
" 表示的是两个不同的文件。
```
java
// 绝对路径示例
File
absoluteFile
=
new
File
(
"/Users/username/example/test.txt"
);
...
...
@@ -157,10 +156,10 @@ if (file.isFile()) {
#### **4)创建、删除功能的方法**
*
`createNewFile()`
:文件不存在,创建一个新的空文件并返回
`true`
,文件存在,不创建文件并返回
`false`
。
*
`delete()`
:删除文件或目录。如果是目录,只有目录为空才能删除。
*
`mkdir()`
:只能创建一级目录,如果父目录不存在,则创建失败。返回 true 表示创建成功,返回 false 表示创建失败。
*
`mkdirs()`
:可以创建多级目录,如果父目录不存在,则会一并创建。返回 true 表示创建成功,返回 false 表示创建失败或目录已经存在。
-
`createNewFile()`
:文件不存在,创建一个新的空文件并返回
`true`
,文件存在,不创建文件并返回
`false`
。
-
`delete()`
:删除文件或目录。如果是目录,只有目录为空才能删除。
-
`mkdir()`
:只能创建一级目录,如果父目录不存在,则创建失败。返回 true 表示创建成功,返回 false 表示创建失败。
-
`mkdirs()`
:可以创建多级目录,如果父目录不存在,则会一并创建。返回 true 表示创建成功,返回 false 表示创建失败或目录已经存在。
**开发中一般用**
`mkdirs()`
;
...
...
@@ -193,8 +192,8 @@ if (directory.mkdirs()) {
#### 5)目录的遍历
*
`String[] list()`
:返回一个 String 数组,表示该 File 目录中的所有子文件或目录。
*
`File[] listFiles()`
:返回一个 File 数组,表示该 File 目录中的所有的子文件或目录。
-
`String[] list()`
:返回一个 String 数组,表示该 File 目录中的所有子文件或目录。
-
`File[] listFiles()`
:返回一个 File 数组,表示该 File 目录中的所有的子文件或目录。
```
java
File
directory
=
new
File
(
"/Users/itwanger/Documents/Github/paicoding"
);
...
...
@@ -221,7 +220,7 @@ for (File fileOrDir : filesAndDirs) {
**listFiles**
在获取指定目录下的文件或者子目录时必须满足下面两个条件:
-
1.
**指定的目录必须存在**
-
2.
**指定的必须是目录。否则容易引发
NullPointerException
异常**
-
2.
**指定的必须是目录。否则容易引发
NullPointerException
异常**
#### 6)递归遍历
...
...
@@ -253,6 +252,120 @@ public static void traverseDirectory(File directory) {
}
```
### RandomAccessFile
RandomAccessFile 是 Java 中一个非常特殊的类,它既可以用来读取文件,也可以用来写入文件。与其他 IO 类(如 FileInputStream 和 FileOutputStream)不同,RandomAccessFile 允许您跳转到文件的任何位置,从那里开始读取或写入。这使得它特别适用于需要在文件中随机访问数据的场景,如数据库系统。
下面是一个使用 RandomAccessFile 的示例,包括写入和读取文件:
```
java
import
java.io.IOException
;
import
java.io.RandomAccessFile
;
public
class
RandomAccessFileDemo
{
public
static
void
main
(
String
[]
args
)
{
String
filePath
=
"logs/javabetter/itwanger.txt"
;
try
{
// 使用 RandomAccessFile 写入文件
writeToFile
(
filePath
,
"Hello, 沉默王二!"
);
// 使用 RandomAccessFile 读取文件
String
content
=
readFromFile
(
filePath
);
System
.
out
.
println
(
"文件内容: "
+
content
);
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
}
private
static
void
writeToFile
(
String
filePath
,
String
content
)
throws
IOException
{
try
(
RandomAccessFile
randomAccessFile
=
new
RandomAccessFile
(
filePath
,
"rw"
))
{
// 将文件指针移动到文件末尾(在此处追加内容)
randomAccessFile
.
seek
(
randomAccessFile
.
length
());
// 写入内容
randomAccessFile
.
writeUTF
(
content
);
}
}
private
static
String
readFromFile
(
String
filePath
)
throws
IOException
{
StringBuilder
content
=
new
StringBuilder
();
try
(
RandomAccessFile
randomAccessFile
=
new
RandomAccessFile
(
filePath
,
"r"
))
{
// 将文件指针移动到文件开始处(从头开始读取)
randomAccessFile
.
seek
(
0
);
content
.
append
(
randomAccessFile
.
readUTF
());
}
return
content
.
toString
();
}
}
```
为了避免中文乱码问题,我们使用 RandomAccessFile 的 writeUTF 和 readUTF 方法,它们将使用 UTF-8 编码处理字符串。大家可以运行一下这段代码,体验一下。
![](
https://cdn.tobebetterjavaer.com/stutymore/file-path-20230331193604.png
)
接下来,会详细介绍一下 RandomAccessFile 的构造方法和常用的方法。
#### 构造方法
RandomAccessFile 主要有两个构造方法:
-
`RandomAccessFile(File file, String mode)`
:使用给定的文件对象和访问模式创建一个新的 RandomAccessFile 实例。
-
`RandomAccessFile(String name, String mode)`
:使用给定的文件名和访问模式创建一个新的 RandomAccessFile 实例。
访问模式 mode 的值可以是:
-
"r":以只读模式打开文件。调用结果对象的任何 write 方法都将导致 IOException。
-
"rw":以读写模式打开文件。如果文件不存在,它将被创建。
-
"rws":以读写模式打开文件,并要求对内容或元数据的每个更新都被立即写入到底层存储设备。这种模式是同步的,可以确保在系统崩溃时不会丢失数据。
-
"rwd":与“rws”类似,以读写模式打开文件,但仅要求对文件内容的更新被立即写入。元数据可能会被延迟写入。
#### 主要方法
-
`long getFilePointer()`
:返回文件指针的当前位置。
-
`long length()`
:返回此文件的长度。
-
`int read()`
:从该文件中读取一个字节数据。
-
`int read(byte[] b)`
:从该文件中读取字节数据并将其存储到指定的字节数组中。
-
`int read(byte[] b, int off, int len)`
:从该文件中读取字节数据并将其存储到指定的字节数组中,从偏移量 off 开始,最多读取 len 个字节。
-
`String readLine()`
:从该文件中读取一行文本。
-
`readUTF()`
:从文件读取 UTF-8 编码的字符串。此方法首先读取两个字节的长度信息,然后根据这个长度读取字符串的 UTF-8 字节。最后,这些字节被转换为 Java 字符串。这意味着当你使用 readUTF 方法读取字符串时,需要确保文件中的字符串是使用 writeUTF 方法写入的,这样它们之间的长度信息和编码方式才能保持一致。
-
`void seek(long pos)`
:将文件指针设置到文件中的 pos 位置。
-
`void write(byte[] b)`
:将指定的字节数组的所有字节写入该文件。
-
`void write(byte[] b, int off, int len)`
:将指定字节数组的部分字节写入该文件,从偏移量 off 开始,写入 len 个字节。
-
`void write(int b)`
:将指定的字节写入该文件。
-
`writeUTF(String str)`
:将一个字符串以 UTF-8 编码写入文件。此方法首先写入两个字节的长度信息,表示字符串的 UTF-8 字节长度,然后写入 UTF-8 字节本身。因此,当你使用 writeUTF 写入字符串时,实际写入的字节数会比字符串的 UTF-8 字节长度多两个字节。这两个字节用于在读取字符串时确定正确的字符串长度。
再来看一个示例,结合前面的讲解,就会彻底掌握 RandomAccessFile。
```
java
File
file
=
new
File
(
"logs/javabetter/itwanger.txt"
);
try
(
RandomAccessFile
raf
=
new
RandomAccessFile
(
file
,
"rw"
))
{
// 写入文件
raf
.
writeUTF
(
"Hello, 沉默王二!"
);
// 将文件指针移动到文件开头
raf
.
seek
(
0
);
// 读取文件内容
String
content
=
raf
.
readUTF
();
System
.
out
.
println
(
"内容: "
+
content
);
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
```
在这个示例中,我们首先创建了一个名为 itwanger.txt 的文件对象。然后我们使用 RandomAccessFile 以读写模式打开这个文件。
接下来,我们使用 writeUTF 方法将字符串"Hello, 沉默王二!"写入文件。然后,我们使用 seek 方法将文件指针移动到文件开头,并使用 readUTF 方法读取文件内容。输出应该是"Hello, 沉默王二!"。
最后,我们使用
[
try-with-resources
](
https://tobebetterjavaer.com/exception/try-with-resources.html
)
语句确保 RandomAccessFile 在操作完成后被正确关闭。
### Apache FileUtils 类
FileUtils 类是 Apache Commons IO 库中的一个类,提供了一些更为方便的方法来操作文件或目录。
...
...
@@ -303,11 +416,11 @@ String extension = FileUtils.getExtension(file.getName());
FileUtil 类是
[
Hutool
](
https://hutool.cn
)
工具包中的文件操作工具类,提供了一系列简单易用的文件操作方法,可以帮助 Java 开发者快速完成文件相关的操作任务。
FileUtil类包含以下几类操作工具:
FileUtil
类包含以下几类操作工具:
-
文件操作:包括文件目录的新建、删除、复制、移动、改名等
-
文件判断:判断文件或目录是否非空,是否为目录,是否为文件等等。
-
绝对路径:针对
ClassPath
中的文件转换为绝对路径文件。
-
绝对路径:针对
ClassPath
中的文件转换为绝对路径文件。
-
文件名:主文件名,扩展名的获取
-
读操作:包括 getReader、readXXX 操作
-
写操作:包括 getWriter、writeXXX 操作
...
...
@@ -346,11 +459,10 @@ FileUtil.readLines(file, "UTF-8").forEach(System.out::println);
更多方法,可以去看一下 hutool 的源码,里面有非常多实用的方法,多看看,绝对能提升不少编程水平。
---
------
---
最近整理了一份牛逼的学习资料,包括但不限于
Java基础部分(JVM、Java集合框架、多线程),还囊括了
**数据库、计算机网络、算法与数据结构、设计模式、框架类Spring、Netty、微服务(Dubbo,消息队列) 网关**
等等等等……详情戳:
[
可以说是2022年全网最全的学习和找工作的PDF
资源了
](
https://tobebetterjavaer.com/pdf/programmer-111.html
)
最近整理了一份牛逼的学习资料,包括但不限于
Java 基础部分(JVM、Java 集合框架、多线程),还囊括了
**数据库、计算机网络、算法与数据结构、设计模式、框架类 Spring、Netty、微服务(Dubbo,消息队列) 网关**
等等等等……详情戳:
[
可以说是 2022 年全网最全的学习和找工作的 PDF
资源了
](
https://tobebetterjavaer.com/pdf/programmer-111.html
)
微信搜
**沉默王二**
或扫描下方二维码关注二哥的原创公众号沉默王二,回复
**111**
即可免费领取。
![](
https://cdn.tobebetterjavaer.com/tobebetterjavaer/images/gongzhonghao.png
)
docs/nio/why.md
浏览文件 @
06e804e4
---
title
:
为什么我们要使用 Java NIO
?
shortTitle
:
为什么我们要使用Java NIO?
title
:
Java 的 NIO 是什么
?
shortTitle
:
Java NIO是什么
category
:
-
Java核心
tag
:
...
...
@@ -9,28 +9,27 @@ description: Java程序员进阶之路,小白的零基础Java教程,为什
head
:
-
-
meta
-
name
:
keywords
content
:
Java,Java SE,Java基础,Java教程,Java程序员进阶之路,Java进阶之路,Java入门,教程,nio
content
:
Java,Java SE,Java基础,Java教程,Java程序员进阶之路,Java进阶之路,Java入门,教程,nio
,java nio
---
我花了几天去了解
**NIO的核心知识点**
,期间看了《Java 编程思想》和《疯狂Java 讲义》的nio模块。
**但是**
,会发现看完了之后还是很
**迷**
,不知道NIO这是干嘛用的,而网上的资料与书上的知识点没有很好地对应。
# 12.1
*
网上的资料很多都以IO的五种模型为基础来讲解NIO,而IO这五种模型其中又涉及到了很多概念:
`同步/异步/阻塞/非阻塞/多路复用`
,
**而不同的人又有不同的理解方式**
。
*
还有涉及到了unix的
`select/epoll/poll/pselect`
,
`fd`
这些关键字,没有相关基础的人看起来简直是天书
*
这就导致了在初学时认为nio远不可及
我花了几天时间去了解
**NIO 的核心知识**
,期间看了《Java 编程思想》和《疯狂 Java 讲义》中的 NIO 模块。
**但是**
,看完之后还是很
**迷**
,不知道 NIO 是干嘛用的,网上的资料和书上的知识点没有很好地对应上。
我在找资料的过程中也收藏了好多讲解NIO的资料,这篇文章就是
**以初学的角度来理解NIO**
。也算是我这两天看NIO的一个总结吧。
-
网上的资料很多都以 IO 的五种模型为基础来讲解 NIO,而 IO 这五种模型其中又涉及到了很多概念:
`同步/异步/阻塞/非阻塞/多路复用`
,
**而不同的人又有不同的理解方式**
。
-
还有涉及到 Unix 的
`select/epoll/poll/pselect`
,
`fd`
这些关键字,没有相关基础的人看起来简直是天书
*
希望大家可以看了之后知道什么是NIO,NIO的核心知识点是什么,会使用
NIO~
我在找资料的过程中也收藏了好多讲解 NIO 的资料,这篇内容就是
**以初学的角度来理解 NIO**
。也算是我这两天看 NIO 的一个总结吧。希望大家可以看了之后知道什么是 NIO,NIO 的核心知识点是什么,以及会使用
NIO~
那么接下来就开始吧,如果文章有错误的地方请大家多多包涵,不吝在评论区指正哦~
> 声明:本文使用JDK1.8
> 声明:本文使用
JDK1.8
JDK 1.4
中的
`java.nio.*包`
中引入新的Java I/O库,其目的是
**提高速度**
。实际上,“旧”的I/O包已经使用NIO
**重新实现过,即使我们不显式的使用NIO
编程,也能从中受益**
。
JDK 1.4
中,
`java.nio.*包`
引入新的 Java I/O 库,其目的是
**提高速度**
。实际上,“旧”的 I/O 包已经使用 NIO
**重新实现过,即使我们不显式的使用 NIO
编程,也能从中受益**
。
*
nio
翻译成 no-blocking io 或者 new io 都无所谓啦,都说得通~
-
nio
翻译成 no-blocking io 或者 new io 都无所谓啦,都说得通~
在《Java
编程思想》读到
**“即使我们不显式的使用NIO编程,也能从中受益”**
的时候,我是挺在意的,所以:我们
**测试**
一下使用NIO复制文件和传统IO
复制文件的性能:
在《Java
编程思想》读到“即使我们不显式的使用 NIO 编程,也能从中受益”的时候,我是挺在意的,所以:我们
**测试**
一下使用 NIO 复制文件和
[
传统 IO
](
https://tobebetterjavaer.com/io/file-path.html
)
复制文件的性能:
```
java
import
java.io.*
;
...
...
@@ -39,16 +38,18 @@ import java.nio.channels.FileChannel;
public
class
SimpleFileTransferTest
{
// 使用传统的 I/O 方法传输文件
private
long
transferFile
(
File
source
,
File
des
)
throws
IOException
{
long
startTime
=
System
.
currentTimeMillis
();
if
(!
des
.
exists
())
des
.
createNewFile
();
// 创建输入输出流
BufferedInputStream
bis
=
new
BufferedInputStream
(
new
FileInputStream
(
source
));
BufferedOutputStream
bos
=
new
BufferedOutputStream
(
new
FileOutputStream
(
des
));
//
将数据源读到的内容写入目的地--使用数组
//
使用数组传输数据
byte
[]
bytes
=
new
byte
[
1024
*
1024
];
int
len
;
while
((
len
=
bis
.
read
(
bytes
))
!=
-
1
)
{
...
...
@@ -59,25 +60,30 @@ public class SimpleFileTransferTest {
return
endTime
-
startTime
;
}
// 使用 NIO 方法传输文件
private
long
transferFileWithNIO
(
File
source
,
File
des
)
throws
IOException
{
long
startTime
=
System
.
currentTimeMillis
();
if
(!
des
.
exists
())
des
.
createNewFile
();
// 创建随机存取文件对象
RandomAccessFile
read
=
new
RandomAccessFile
(
source
,
"rw"
);
RandomAccessFile
write
=
new
RandomAccessFile
(
des
,
"rw"
);
// 获取文件通道
FileChannel
readChannel
=
read
.
getChannel
();
FileChannel
writeChannel
=
write
.
getChannel
();
ByteBuffer
byteBuffer
=
ByteBuffer
.
allocate
(
1024
*
1024
);
//1M缓冲区
// 创建并使用 ByteBuffer 传输数据
ByteBuffer
byteBuffer
=
ByteBuffer
.
allocate
(
1024
*
1024
);
while
(
readChannel
.
read
(
byteBuffer
)
>
0
)
{
byteBuffer
.
flip
();
writeChannel
.
write
(
byteBuffer
);
byteBuffer
.
clear
();
}
// 关闭文件通道
writeChannel
.
close
();
readChannel
.
close
();
long
endTime
=
System
.
currentTimeMillis
();
...
...
@@ -86,66 +92,51 @@ public class SimpleFileTransferTest {
public
static
void
main
(
String
[]
args
)
throws
IOException
{
SimpleFileTransferTest
simpleFileTransferTest
=
new
SimpleFileTransferTest
();
File
sourse
=
new
File
(
"
F:\\电影\\
[电影天堂www.dygod.cn]猜火车-cd1.rmvb"
);
File
des
=
new
File
(
"
X:\\Users\\ozc\\Desktop\\
io.avi"
);
File
nio
=
new
File
(
"
X:\\Users\\ozc\\Desktop\\
nio.avi"
);
File
sourse
=
new
File
(
"[电影天堂www.dygod.cn]猜火车-cd1.rmvb"
);
File
des
=
new
File
(
"io.avi"
);
File
nio
=
new
File
(
"nio.avi"
);
// 比较传统的 I/O 和 NIO 传输文件的时间
long
time
=
simpleFileTransferTest
.
transferFile
(
sourse
,
des
);
System
.
out
.
println
(
time
+
":普通字节流时间"
);
long
timeNio
=
simpleFileTransferTest
.
transferFileWithNIO
(
sourse
,
nio
);
System
.
out
.
println
(
timeNio
+
":NIO时间"
);
}
}
```
我分别测试了文件大小为13M,40M,200M的:
![](
https://cdn.tobebetterjavaer.com/tobebetterjavaer/images/nio/why-d5118350-471f-4998-abb2-4e82c7a50344.jpg
)
在我给出实际的结论之前:
![](
https://cdn.tobebetterjavaer.com/tobebetterjavaer/images/nio/why-ffcb8770-5f0a-41e9-8534-f92a6f931a49.jpg
)
-
对于较小的文件,NIO 和普通 IO 之间的性能差异可能不会非常明显,因为文件本身较小,复制过程较快。
-
对于较大的文件,使用 NIO 的性能可能会明显优于普通 IO。这是因为 NIO 使用了更高效的缓冲区和通道机制,可以在内存中进行更快的数据传输。
![](
https://cdn.tobebetterjavaer.com/stutymore/why-20230331191748.png
)
为什么要使用 NIO?
可以看到使用过 NIO 重新实现过的
**传统 IO 根本不虚**
,在大文件下效果还比 NIO 要好(当然了,个人几次的测试,或许不是很准)
![](
https://cdn.tobebetterjavaer.com/tobebetterjavaer/images/nio/why-0425087f-7878-466b-b02a-a802444e7405.jpg
)
-
而 NIO 要有一定的学习成本,也没有传统 IO 那么好理解。
那这意味着我们
**可以不使用/学习 NIO 了吗**
?
答案是
**否定**
的,IO 操作往往在
**两个场景**
下会用到:
为什么要使用NIO?
-
文件 IO
-
网络 IO
可以看到使用过NIO重新实现过的
**传统IO根本不虚**
,在大文件下效果还比NIO要好(当然了,个人几次的测试,或许不是很准)
NIO 的
**魅力:在网络中使用 IO 就可以体现出来了**
!
*
而NIO要有一定的学习成本,也没有传统IO那么好理解。
-
后面会说到网络中使用 NIO,不急哈~
那这意味着我们
**可以不使用/学习NIO了吗**
?
> 参考链接:[https://www.zhihu.com/question/29005375/answer/667616386](https://www.zhihu.com/question/29005375/answer/667616386),整理:沉默王二
答案是
**否定**
的,IO操作往往在
**两个场景**
下会用到:
*
文件IO
*
网络IO
NIO的
**魅力:在网络中使用IO就可以体现出来了**
!
*
后面会说到网络中使用NIO,不急哈~
>参考链接:[https://www.zhihu.com/question/29005375/answer/667616386](https://www.zhihu.com/question/29005375/answer/667616386),整理:沉默王二
---------
---
最近整理了一份牛逼的学习资料,包括但不限于
Java基础部分(JVM、Java集合框架、多线程),还囊括了
**数据库、计算机网络、算法与数据结构、设计模式、框架类Spring、Netty、微服务(Dubbo,消息队列) 网关**
等等等等……详情戳:
[
可以说是2022年全网最全的学习和找工作的PDF
资源了
](
https://tobebetterjavaer.com/pdf/programmer-111.html
)
最近整理了一份牛逼的学习资料,包括但不限于
Java 基础部分(JVM、Java 集合框架、多线程),还囊括了
**数据库、计算机网络、算法与数据结构、设计模式、框架类 Spring、Netty、微服务(Dubbo,消息队列) 网关**
等等等等……详情戳:
[
可以说是 2022 年全网最全的学习和找工作的 PDF
资源了
](
https://tobebetterjavaer.com/pdf/programmer-111.html
)
微信搜
**沉默王二**
或扫描下方二维码关注二哥的原创公众号沉默王二,回复
**111**
即可免费领取。
![](
https://cdn.tobebetterjavaer.com/tobebetterjavaer/images/gongzhonghao.png
)
二哥的 Java 进阶之路.md
浏览文件 @
06e804e4
...
...
@@ -19207,13 +19207,13 @@ File 的常用方法主要分为获取功能、获取绝对路径和相对路径
测试代码如下【注意测试以你自己的电脑文件夹为准】:
```java
File f = new File("/Users/username/aaa/bbb.java");
File f = new File("/Users/username/aaa/bbb.java");
System.out.println("文件绝对路径:"+f.getAbsolutePath());
System.out.println("文件构造路径:"+f.getPath());
System.out.println("文件名称:"+f.getName());
System.out.println("文件长度:"+f.length()+"字节");
File f2 = new File("/Users/username/aaa");
File f2 = new File("/Users/username/aaa");
System.out.println("目录绝对路径:"+f2.getAbsolutePath());
System.out.println("目录构造路径:"+f2.getPath());
System.out.println("目录名称:"+f2.getName());
...
...
@@ -19233,7 +19233,6 @@ System.out.println("目录长度:"+f2.length());
- 在 Windows 操作系统中,文件系统默认是不区分大小写的,即在文件系统中,文件名和路径的大小写可以混合使用。例如,"`C:\Users\username\Documents\example.txt`" 和 "`C:\Users\Username\Documents\Example.txt`" 表示的是同一个文件。但是,Windows 操作系统提供了一个区分大小写的选项,可以在格式化磁盘时选择启用,这样文件系统就会区分大小写。
- 在 macOS 和 Linux 等 Unix 系统中,文件系统默认是区分大小写的。例如,在 macOS 系统中,"`/Users/username/Documents/example.txt`" 和 "`/Users/username/Documents/Example.txt`" 表示的是两个不同的文件。
```java
// 绝对路径示例
File absoluteFile = new File("/Users/username/example/test.txt");
...
...
@@ -19281,10 +19280,10 @@ if (file.isFile()) {
#### **4)创建、删除功能的方法**
*
`createNewFile()` :文件不存在,创建一个新的空文件并返回`true`,文件存在,不创建文件并返回`false`。
*
`delete()` :删除文件或目录。如果是目录,只有目录为空才能删除。
*
`mkdir()` :只能创建一级目录,如果父目录不存在,则创建失败。返回 true 表示创建成功,返回 false 表示创建失败。
*
`mkdirs()` :可以创建多级目录,如果父目录不存在,则会一并创建。返回 true 表示创建成功,返回 false 表示创建失败或目录已经存在。
-
`createNewFile()` :文件不存在,创建一个新的空文件并返回`true`,文件存在,不创建文件并返回`false`。
-
`delete()` :删除文件或目录。如果是目录,只有目录为空才能删除。
-
`mkdir()` :只能创建一级目录,如果父目录不存在,则创建失败。返回 true 表示创建成功,返回 false 表示创建失败。
-
`mkdirs()` :可以创建多级目录,如果父目录不存在,则会一并创建。返回 true 表示创建成功,返回 false 表示创建失败或目录已经存在。
**开发中一般用**`mkdirs()`;
...
...
@@ -19317,8 +19316,8 @@ if (directory.mkdirs()) {
#### 5)目录的遍历
*
`String[] list()` :返回一个 String 数组,表示该 File 目录中的所有子文件或目录。
*
`File[] listFiles()` :返回一个 File 数组,表示该 File 目录中的所有的子文件或目录。
-
`String[] list()` :返回一个 String 数组,表示该 File 目录中的所有子文件或目录。
-
`File[] listFiles()` :返回一个 File 数组,表示该 File 目录中的所有的子文件或目录。
```java
File directory = new File("/Users/itwanger/Documents/Github/paicoding");
...
...
@@ -19345,7 +19344,7 @@ for (File fileOrDir : filesAndDirs) {
**listFiles**在获取指定目录下的文件或者子目录时必须满足下面两个条件:
- 1. **指定的目录必须存在**
- 2. **指定的必须是目录。否则容易引发
NullPointerException
异常**
- 2. **指定的必须是目录。否则容易引发
NullPointerException
异常**
#### 6)递归遍历
...
...
@@ -19377,6 +19376,120 @@ public static void traverseDirectory(File directory) {
}
```
### RandomAccessFile
RandomAccessFile 是 Java 中一个非常特殊的类,它既可以用来读取文件,也可以用来写入文件。与其他 IO 类(如 FileInputStream 和 FileOutputStream)不同,RandomAccessFile 允许您跳转到文件的任何位置,从那里开始读取或写入。这使得它特别适用于需要在文件中随机访问数据的场景,如数据库系统。
下面是一个使用 RandomAccessFile 的示例,包括写入和读取文件:
```java
import java.io.IOException;
import java.io.RandomAccessFile;
public class RandomAccessFileDemo {
public static void main(String[] args) {
String filePath = "logs/javabetter/itwanger.txt";
try {
// 使用 RandomAccessFile 写入文件
writeToFile(filePath, "Hello, 沉默王二!");
// 使用 RandomAccessFile 读取文件
String content = readFromFile(filePath);
System.out.println("文件内容: " + content);
} catch (IOException e) {
e.printStackTrace();
}
}
private static void writeToFile(String filePath, String content) throws IOException {
try (RandomAccessFile randomAccessFile = new RandomAccessFile(filePath, "rw")) {
// 将文件指针移动到文件末尾(在此处追加内容)
randomAccessFile.seek(randomAccessFile.length());
// 写入内容
randomAccessFile.writeUTF(content);
}
}
private static String readFromFile(String filePath) throws IOException {
StringBuilder content = new StringBuilder();
try (RandomAccessFile randomAccessFile = new RandomAccessFile(filePath, "r")) {
// 将文件指针移动到文件开始处(从头开始读取)
randomAccessFile.seek(0);
content.append(randomAccessFile.readUTF());
}
return content.toString();
}
}
```
为了避免中文乱码问题,我们使用 RandomAccessFile 的 writeUTF 和 readUTF 方法,它们将使用 UTF-8 编码处理字符串。大家可以运行一下这段代码,体验一下。
![](https://cdn.tobebetterjavaer.com/stutymore/file-path-20230331193604.png)
接下来,会详细介绍一下 RandomAccessFile 的构造方法和常用的方法。
#### 构造方法
RandomAccessFile 主要有两个构造方法:
- `RandomAccessFile(File file, String mode)`:使用给定的文件对象和访问模式创建一个新的 RandomAccessFile 实例。
- `RandomAccessFile(String name, String mode)`:使用给定的文件名和访问模式创建一个新的 RandomAccessFile 实例。
访问模式 mode 的值可以是:
- "r":以只读模式打开文件。调用结果对象的任何 write 方法都将导致 IOException。
- "rw":以读写模式打开文件。如果文件不存在,它将被创建。
- "rws":以读写模式打开文件,并要求对内容或元数据的每个更新都被立即写入到底层存储设备。这种模式是同步的,可以确保在系统崩溃时不会丢失数据。
- "rwd":与“rws”类似,以读写模式打开文件,但仅要求对文件内容的更新被立即写入。元数据可能会被延迟写入。
#### 主要方法
- `long getFilePointer()`:返回文件指针的当前位置。
- `long length()`:返回此文件的长度。
- `int read()`:从该文件中读取一个字节数据。
- `int read(byte[] b)`:从该文件中读取字节数据并将其存储到指定的字节数组中。
- `int read(byte[] b, int off, int len)`:从该文件中读取字节数据并将其存储到指定的字节数组中,从偏移量 off 开始,最多读取 len 个字节。
- `String readLine()`:从该文件中读取一行文本。
- `readUTF()`:从文件读取 UTF-8 编码的字符串。此方法首先读取两个字节的长度信息,然后根据这个长度读取字符串的 UTF-8 字节。最后,这些字节被转换为 Java 字符串。这意味着当你使用 readUTF 方法读取字符串时,需要确保文件中的字符串是使用 writeUTF 方法写入的,这样它们之间的长度信息和编码方式才能保持一致。
- `void seek(long pos)`:将文件指针设置到文件中的 pos 位置。
- `void write(byte[] b)`:将指定的字节数组的所有字节写入该文件。
- `void write(byte[] b, int off, int len)`:将指定字节数组的部分字节写入该文件,从偏移量 off 开始,写入 len 个字节。
- `void write(int b)`:将指定的字节写入该文件。
- `writeUTF(String str)`:将一个字符串以 UTF-8 编码写入文件。此方法首先写入两个字节的长度信息,表示字符串的 UTF-8 字节长度,然后写入 UTF-8 字节本身。因此,当你使用 writeUTF 写入字符串时,实际写入的字节数会比字符串的 UTF-8 字节长度多两个字节。这两个字节用于在读取字符串时确定正确的字符串长度。
再来看一个示例,结合前面的讲解,就会彻底掌握 RandomAccessFile。
```java
File file = new File("logs/javabetter/itwanger.txt");
try (RandomAccessFile raf = new RandomAccessFile(file, "rw")) {
// 写入文件
raf.writeUTF("Hello, 沉默王二!");
// 将文件指针移动到文件开头
raf.seek(0);
// 读取文件内容
String content = raf.readUTF();
System.out.println("内容: " + content);
} catch (IOException e) {
e.printStackTrace();
}
```
在这个示例中,我们首先创建了一个名为 itwanger.txt 的文件对象。然后我们使用 RandomAccessFile 以读写模式打开这个文件。
接下来,我们使用 writeUTF 方法将字符串"Hello, 沉默王二!"写入文件。然后,我们使用 seek 方法将文件指针移动到文件开头,并使用 readUTF 方法读取文件内容。输出应该是"Hello, 沉默王二!"。
最后,我们使用[try-with-resources](https://tobebetterjavaer.com/exception/try-with-resources.html)语句确保 RandomAccessFile 在操作完成后被正确关闭。
### Apache FileUtils 类
FileUtils 类是 Apache Commons IO 库中的一个类,提供了一些更为方便的方法来操作文件或目录。
...
...
@@ -19427,11 +19540,11 @@ String extension = FileUtils.getExtension(file.getName());
FileUtil 类是 [Hutool](https://hutool.cn) 工具包中的文件操作工具类,提供了一系列简单易用的文件操作方法,可以帮助 Java 开发者快速完成文件相关的操作任务。
FileUtil类包含以下几类操作工具:
FileUtil
类包含以下几类操作工具:
- 文件操作:包括文件目录的新建、删除、复制、移动、改名等
- 文件判断:判断文件或目录是否非空,是否为目录,是否为文件等等。
- 绝对路径:针对
ClassPath
中的文件转换为绝对路径文件。
- 绝对路径:针对
ClassPath
中的文件转换为绝对路径文件。
- 文件名:主文件名,扩展名的获取
- 读操作:包括 getReader、readXXX 操作
- 写操作:包括 getWriter、writeXXX 操作
...
...
@@ -19470,9 +19583,9 @@ FileUtil.readLines(file, "UTF-8").forEach(System.out::println);
更多方法,可以去看一下 hutool 的源码,里面有非常多实用的方法,多看看,绝对能提升不少编程水平。
---
------
---
最近整理了一份牛逼的学习资料,包括但不限于
Java基础部分(JVM、Java集合框架、多线程),还囊括了 **数据库、计算机网络、算法与数据结构、设计模式、框架类Spring、Netty、微服务(Dubbo,消息队列) 网关** 等等等等……详情戳:[可以说是2022年全网最全的学习和找工作的PDF
资源了](https://tobebetterjavaer.com/pdf/programmer-111.html)
最近整理了一份牛逼的学习资料,包括但不限于
Java 基础部分(JVM、Java 集合框架、多线程),还囊括了 **数据库、计算机网络、算法与数据结构、设计模式、框架类 Spring、Netty、微服务(Dubbo,消息队列) 网关** 等等等等……详情戳:[可以说是 2022 年全网最全的学习和找工作的 PDF
资源了](https://tobebetterjavaer.com/pdf/programmer-111.html)
微信搜 **沉默王二** 或扫描下方二维码关注二哥的原创公众号沉默王二,回复 **111** 即可免费领取。
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录