前言:上一篇我们讲了NIO的基础还有三大核心组成部分,这篇主要讲解NIO的其他类(线程间数据单向交互的管道Pipe,以及Path 、Paths 、Files类介绍及使用)。
一、管道 (Pipe)
Java NIO 管道是2个线程之间的单向数据连接。Pipe有一个source通道和一个sink通道。数据会被写到sink通道,从source通道读取。
我个人理解是channel用于io传输,这里的pipe只是附带的一个小功能,用线程间数据单向交互。如有错误欢迎指正交流。
Pipe原理图如下:
样例代码:
public class TestPipe {
@Test
public void test1()throws IOException{
//1.获取管道
Pipe pipe=Pipe.open();
//2.将缓冲区中的数据写入管道
ByteBuffer buf=ByteBuffer.allocate(1024);
Pipe.SinkChannel sinkChannel=pipe.sink();
buf.put("通过单向管道发送数据".getBytes());
buf.flip();
sinkChannel.write(buf);
//3.读取缓冲区中的数据
Pipe.SourceChannel sourceChannel=pipe.source();
buf.flip();
int len=sourceChannel.read(buf);
System.out.println(new String(buf.array(),0,len));
sourceChannel.close();
sinkChannel.close();
}
}
二、NIO.2 – Path 、Paths 、Files
基于异步Channel的IO,NIO新增Path接口,Paths工具类,Files工具类。 这些接口和工具类对NIO中的功能进行了高度封装,大大简化了文件系统的IO编程。
1、Path接口
在java.io及java.nio中,是通过File类来访问文件系统(文件和目录都用File类表示),但是File类不能利用特定文件系统的特性,且性能不高,因此在NIO.2中引入了Path接口。
Path接口表示的是一个与平台无关的路径(文件和目录都用Path表示)。
-
boolean endsWith(String path) : 判断是否以 path 路径结束
-
boolean startsWith(String path) : 判断是否以 path 路径开始
-
boolean isAbsolute() : 判断是否是绝对路径
-
Path getFileName() : 返回与调用 Path 对象关联的文件名
-
Path getName(int idx) : 返回的指定索引位置 idx 的路径名称
-
int getNameCount() : 返回Path 根目录后面元素的数量
-
Path getParent() :返回Path对象包含整个路径,不包含Path 对象指定的文件路径
-
Path getRoot() :返回调用 Path 对象的根路径
-
Path resolve(Path p) :将相对路径解析为绝对路径
-
Path toAbsolutePath() : 作为绝对路径返回调用 Path 对象
-
String toString() : 返回调用 Path 对象的字符串表示形式
2、Files工具类
java.nio.file.Files 用于操作文件或目录的工具类。(在旧的IO中的操作文件的类是File,但是File类只能操作文件(创建,删除,修改属性等),但是不能修改文件的内容。但是Files工具类可以直接写文件。)
用于操作文件的方法:
- Path copy(Path src, Path dest, CopyOption … how) : 文件的复制
- Path createDirectory(Path path, FileAttribute< ? > … attr) : 创建一个目录
- Path createFile(Path path, FileAttribute< ? > … arr) : 创建一个文件
- void delete(Path path) : 删除一个文件
- Path move(Path src, Path dest, CopyOption…how) : 将 src 移动到 dest 位置
- long size(Path path) : 返回 path 指定文件的大小
用于判断的方法:
- boolean exists(Path path, LinkOption … opts) : 判断文件是否存在
- boolean isDirectory(Path path, LinkOption … opts) : 判断是否是目录
- boolean isExecutable(Path path) : 判断是否是可执行文件
- boolean isHidden(Path path) : 判断是否是隐藏文件
- boolean isReadable(Path path) : 判断文件是否可读
- boolean isWritable(Path path) : 判断文件是否可写
- boolean notExists(Path path, LinkOption … opts) : 判断文件是否不存在
- public static < A extends BasicFileAttributes> A readAttributes(Path path,Class< A > type,LinkOption…options) : 获取与 path 指定的文件相关联的属性。
用于操作内容的方法:
- SeekableByteChannel newByteChannel(Path path, OpenOption…how) : 获取与指定文件的连接,how 指定打开方式。
- DirectoryStream newDirectoryStream(Path path) : 打开 path 指定的目录
- InputStream newInputStream(Path path, OpenOption…how):获取 InputStream 对象
- OutputStream newOutputStream(Path path, OpenOption…how) : 获取 OutputStream 对象
应用代码,懒得写了直接搬大佬的代码吧:
package nio;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
//Files工具类通常结合Path对象使用
public class FileTest {
public static void main(String[] args) throws FileNotFoundException, IOException {
//将传统io读写文件高度封装之后,在NIO.2中拷贝文件只需要调用File工具类的copy()方法
Files.copy(Paths.get("tmp.txt"), new FileOutputStream("tmp2.txt"));
//是否为隐藏文件
System.out.println("tmp.txt是否为隐藏文件: "+Files.isHidden(Paths.get("tmp.txt")));
//一次性读取所有行 , 需要指定编码规则
List<String> lines = Files.readAllLines(Paths.get("tmp.txt"), Charset.forName("gbk"));
System.out.println(lines);
//文件大小
System.out.println("tmp.txt文件大小为: "+Files.size(Paths.get("tmp.txt")));
List<String> poem = new ArrayList<>();
poem.add("海阔凭鱼跃");
poem.add("天高任鸟飞");
//直接将字符串数组写入文件
Files.write(Paths.get("tmp.txt"), poem, Charset.forName("gbk"));
}
}
输出结果为:
tmp.txt是否为隐藏文件: false
[海阔凭鱼跃, 天高任鸟飞]
tmp.txt文件大小为: 24