导航菜单
首页 » 无极3注册 » 正文

蓬莱-Java面试必问通讯结构NIO,原理详解

NIO

新的输入/输出 (NIO) 库是在 JDK 1.4 中引进的,弥补了本来的 I/O 的缺乏,供给了高速的、面向块的 I/O。

NIO中心组件:

  • 通道(Channels)缓冲区(Buffers)选择器(Selectors)

流与块

I/O 与 NIO 最重要的差异是数据打包和传输的办法,I/O 以流的办法处理数据,而 NIO 以块的办法处理数据。

面向流的 I/O 一次处理一个字节数据:一个输入流发生一个字节数据,一个输出流消费一个字节数据。 为流式数据创立过滤器十分简略,链接几个过滤器,以便每个过滤器只担任杂乱处理机制的一部分。晦气的一面是,面向流的 I/O 一般适当慢。

面向块的 I/O 一次处理一个数据块,按块处理数据比按流处理数据要快得多。 可是面向块的 I/O 短少一些面向流的 I/O 所具有的高雅性和简略性。

I/O 包和 NIO 现已很好地集成了,java.io.* 现已以 NIO 为根底从头完成了,所以现在它能够运用 NIO 的一些特性。 例如,java.io.* 包中的一些类包括以块的办法读写数蓬莱-Java面试必问通讯结构NIO,原理详解据的办法,这使得即便在面向流的体系中,处理速度也会更快。

通道与缓冲区

1. 通道

通道 Channel 是对原 I/O 包中的流的模仿,能够经过它读取和写入数据。

通道与流的不同之处在于,流只能在一个方向上移动(一个流有必要是 InputStream 或许 OutputStream 的子类), 而通道是双向的,能够用于读、写或许一起用于读写。

通道包括以下类型:

  • FileChannel:从文件中读写数据;DatagramChannel:经过 UDP 读写网络中数据;SocketChannel:经过 TCP 读写网络中数据;ServerSocketChannel:能够监听新进来的 TCP 衔接,对每一个新进来的衔接都会创立一个 SocketChannel。

2. 缓冲区

发送给一个通道的一切数据都有必要首要放到缓冲区中,同样地,从通道中读取的任何数据都要先读到缓冲区中。也就是说,不会直接对通道进行读写数据,而是要先经过缓冲区。

缓冲区实质上是一个数组,但它不仅仅是一个数组。缓冲区供给了对数据的结构化拜访,而且还能够盯梢体系的读/写进程。

缓冲区包括以下类型:

  • ByteBufferCharBufferShortBufferIntBufferLongBufferFloatBufferDoubleBuffer

缓冲区状态变量

  • capacity:最大容量;position:当时现已读写的字节数;limit:还能够读写的字节数。

状态变量的改动进程举例:

① 新建一个巨细为 8 个字节的缓冲区,此刻 position 为 0,而 limit = capacity = 8。capacity 变量不会改动,下面的讨论会疏忽它。

② 从输入通道中读取 5 个字节数据写入缓冲区中,此刻 position 为 5,limit 坚持不变。

③ 在将缓冲区的数据写到输出通道之前,需求先调用 flip() 办法,这个办法将 limit 设置为当时 position,并将 position 设置为 0。

④ 从缓冲区中取 4 个字节到输出缓冲中,此刻 position 设为 4。

⑤ 最终需求调用 clear() 办法来清空缓冲区,此刻 position 和 limit 都被设置为开始方位。

文件 NIO 实例

FileChannel的运用

  1. 敞开FileChannel从FileChannel读取数据/写入数据

3.封闭FileChannel

public class FileChannelDemo {
public static void main(String[] args) throws IOException {
//1.创立一个RandomAccessFile(随机拜访文件)方针经过RandomAccessFile方针的getChannel()办法。
RandomAccessFile raf=new RandomAccessFile("demo6.txt","rw");
FileChannel fc=raf.getChannel();
//运用FileChannel的read()办法读取数据:
ByteBuffer byteBuffer=ByteBuffer.allocate(1024);
int bys=fc.read(byteBuffer);
//运用FileChannel的write()办法写入数据:
ByteBuffer byteBuffer2=ByteBuffer.allocate(1024);
byteBuffer2.put("hello".getBytes());
fc.write(byteBuffer2);

//3.封闭FileChannel
fc.close();
}
}
  • 以下展现了运用 NIO 快速仿制文件的实例:
public c蓬莱-Java面试必问通讯结构NIO,原理详解lass CopyFile {
public static void main(String[] args) throws IOException {
String srcFile="国旗歌.mp4";
String destFile="demo3.mp4";
long start = System.currentTimeMillis();
//copyFile(srcFile,destFile); //共耗时:75309毫秒
//copyFile2(srcFile,destFile); //共耗时:153毫秒
//copyFile3(srcFile,destFile);//共耗时:282毫秒
//copyFile4(srcFile,destFile);//共耗时:44毫秒
copyFile5(srcFile,destFile);//共耗时:共耗时:113毫秒
long end = System.currentTimeMillis();
System.out.println("共耗时:" + (end - start) + "毫秒");
}
/**
* 根本字节省一次读写一个字节
*/
public static void copyFile(String srcFile,String destFile) throws IOException {
FileInputStream fis=new FileInputStream(srcFile);
FileOutputStream fos=new FileOutputStream(destFile);
int by=0;
while((by=fis.read())!=-1){
fos.write(by);
}
fis.close();
fos.close();
}
/**
* 根本字节省一次读写一个字节数组
*/
public static void copyFile2(String srcFile,String destFile) throws IOException{
FileInputStream fis=new FileInputStream(srcFile);
FileOutputStream fos=new FileOutputStream(destFile);
int len=0;
byte[] bys=new byte[1024];
while((len=fis.read(bys))!=-1){
fos.write(bys,0,len);
}
fis.close();
fos.close();
}
/**
* 高效字节省一次读写一个字节
*/
public static void copyFile3(String srcFile,String destFile) throws IOException{
BufferedInputStream bis=new BufferedInputStream(new FileInputStream(srcFile));
BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream(destFile));
int by=0;
while((by=bis.read())!=-1){
bos.write(by);
}
bis.close();
bos.close();
}
/**
* 高效字节省一次读写一个字节数组
*/
public static void copyFile4(String srcFile,String destFile) throws IOException{
BufferedInputStream bis=new BufferedInputStream(new FileInputStream(srcFile));
BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream(destFile));
int len=0;
byte[] bys=new byte[1024];
while((len=bis.read(bys))!=-1){
bos.write(bys,0,len);
}
bis.close();
bos.close();
}
/**
* 运用FileChannel仿制文件
*/
public static void copyFile5(String srcFile,String destFile) throws IOException{
FileInputStream fis=new FileInputStream(srcFile);
//获取输入字节省的文件通道
FileChannel fcin=fis.getChannel();
FileOutputStream fos=new FileOutputStream(destFile);
//获取输出字节省的文件通道
FileChannel fcout=fos.getChannel();
//为缓冲区分配 1024 个字节
ByteBuffer buffer = ByteBuffer.allocateDirect(1024);
while(true){
//从输入通道中读取数据到缓冲区中
int r = fcin.read(buffer);
// read() 回来 -1 表明 EOF
if(r==-1){
break;
}
//切换读写
buffer.flip();
//把缓冲区的内容写入输出文件中
fcout.write(buffer);
//清空缓冲区
buffer.clear();
}
}
}

SocketChannel和ServerSocketChannel的运用

SocketChannel用于创立根据TCP协议的客户端方针,由于SocketChannel中不存在accept()办法, 所以,它不能成为一个服务端程序。 经过connect()办法,SocketChannel方针能够衔接到其他TCP服务器程序。

ServerSocketChannel答应咱们监听TCP协议恳求,经过ServerSocketChannel的**accept()**办法创立一个SocketChannel方针用户从客户端读/写数据。

  1. 服务端:经过ServerSocketChannel 绑定ip地址和端口号经过ServerSocketChannel的accept()办法创立一个SocketChannel方针用户从客户端读/写数据创立读数据/写数据缓冲区方针来读取客户端数据或向客户端发送数据封闭SocketChannel和ServerSocketChannel
public class Server {
public static void main(String[] args) throws IOException {
//经过ServerSocketChannel 的open()办法创立一个ServerSocketChannel方针
ServerSocketChannel ssc=ServerSocketChannel.open();
//1. 经过ServerSocketChannel 绑定ip地址和端口号
ssc.socket().bind(new InetSocketAddress(InetAddress.getByName("LAPTOP-D9966H06"),8888));
//2. 经过ServerSocketChannel的accept()办法创立一个SocketChannel方针用户从客户端读/写数据
SocketChannel sc=ssc.accept();
//3. 创立读数据/写数据缓冲区方针来读取客户端数据或向客户端发送数据
//读取客户端发送的数据
ByteBuffer buffer=ByteBuffer.allocate(1024);
//从通道中读取数据到缓冲区
sc.read(buffer);
StringBuffer sb=new StringBuffer();
buffer.flip();
while(buffer.hasRemaining()){
sb.append((char)buffer.get());
}
System.out.println(sb.toString());
ByteBuffer buffer2=ByteBuffer.allocate(1024);
//向客户端发送数据
buffer2.put("data has been received.".getBytes());
buffer2.flip();
sc.write(buffer2);
//4. 封闭SocketChannel和ServerSocketChannel
sc.close();
ssc.close();
}
}
  • 客户端:

1.经过SocketChannel衔接到长途服务器

2.创立读数据/写数据缓冲区方针来读取服务端数据或向服务端发送数据

3.封闭SocketChannel

public class Client {
public static void main(String[] args) throws IOException {
//1.经过SocketChannel衔接到长途服务器
SocketChannel sc=SocketChannel.open();
sc.connect(new InetSocketAddress(InetAddress.getByName("LAPTOP-D9966H06"),8888));
//2.创立读数据/写数据缓冲区方针来读取服务端数据或向服务端发送数据
//向通道中写入数据
ByteBuffer buffer=ByteBuffer.allocate(1024);
buffer.put("hello".getBytes());
buffer.flip();
sc.write(buffer);
//读取从客户端中获取的数据
ByteBuffer buffer2=ByteBuffer.allocate(1024);
sc.read(buffer2);
StringBuffer sb=new StringBuffer();
buffer2.flip();
while(buffer2.hasRemaining()){
sb.append((char)buffer2.get());
}
System.out.println(sb.toString());
//3.封闭SocketChannel
sc.close();
}
}

DatagramChannel的运用

DataGramChannel,类似于java 网络编程的DatagramSocket类; 运用UDP进行网络传输, UDP是无衔接,面向数据报文段的协议。

  • 服务端:
public class Server {
public static void main(String[] args) throws IOException {
DatagramChannel dc= DatagramChannel.open();
dc.bind(new InetSocketAddress(InetAddress.getByName("LAPTOP-D9966H06"),8888));
//创立读数据/写数据缓冲区方针来读取客户端数据或向客户端发送数据
//读取客户端发送的数据
ByteBuffer buffer=ByteBuffer.allocate(1024);
//从通道中读取数据到缓冲区
dc.receive(buffer);
StringBuffer sb=new StringBuffer();
buffer.flip();
while(buffer.hasRemaining()){
sb.append((char)buffer.get());
}
System.out.println(sb.toString());
ByteBuffer buffer2=ByteBuffer.allocate(1024);
//向客户端发送数据
buffer2.put("data has been received.".getBytes());
buffer2.flip();
dc.send(buffer2,new InetSocketAddress(InetAddress.getByName("LAPTOP-D9966H06"),9999));

dc.close();
}
}
  • 客户端:
public class Client {
public static void main(String[] args) throws IOException {
DatagramChannel dc= DatagramChannel.open();
dc.bind(new InetSocketAddress(InetAddress.getByName("LAPTOP-D9966H06"),9999));
//创立读数据/写数据缓冲区方针来读取服务端数据或向服务端发送数据
//向通道中写入数据
ByteBuffer buffer=ByteBuffer.allocate(1024);
buffer.put("hello".getBytes());
buffer.flip();
dc.send(buffer,new InetSocketAddress(InetAddress.getByName("LAPTOP-D9966H06"),8888));
//读取从客户端中获取的数据
ByteBuffer buffer2=ByteBuffer.allocate(1024);
dc.receive(buffer2);
StringBuffer sb=new StringBuffer();
buffer2.flip();
while(buffer2.hasRemaining()){
sb.append((char)buffer2.get());
}
System.out.println(sb.toString());

dc.close();
}
}

通道之间的数据传输

在Java NIO中假如一个channel是FileChannel类型的,那么他能够直接把数据传输到另一个channel。

transferFrom() :transferFrom办法把数据从通道源传输到FileChannel
transferTo() :transferTo办法把FileChannel数据传输到另一个FileChhannel
public static void copyFile6(String srcFile,String destFile) throws IOException {
FileInputStream fis = new FileInputStream(srcFile);
//获取输入字节省的文件通道
FileChannel fcin = fis.getChannel();
FileOutputStream fos = new FileOutputStream(destFile);
//获取输出字节省的文件通道
FileChannel fcout = fos.getChannel();
//fcin通道中读出count bytes ,并写入fcout通道中
//fcin.transferTo(0,fcin.size(),fcout);
//或许
fcout.transferFrom(fcin,0,fcin.size());
}

选择器

NIO 常常被叫做非堵塞 IO,首要是由于 NIO 在网络通信中的非堵塞特性被广泛运用。

NIO 完成了 IO 多路复用中的 Reactor 模型,一个线程 Thread 运用一个选择器 Selector 经过轮询的办法 去监听多个通道 Channel 上的事情,然后让一个线程就能够处理多个事情。

经过装备监听的通道 Channel 为非堵塞,那么当 Channel 上的 IO 事情还未抵达时, 就不会进入堵塞状态一向等候,而是持续轮询其它 Channel,找到 IO 事情现已抵达的 Channel 履行。

由于创立和切换线程的开支很大,因而运用一个线程来处理多个事情而不是一个线程处理一个事情, 关于 IO 密集型的运用具有很好地功能。

应该留意的是,只要套接字 Channel 才干装备为非堵塞,而 FileChannel 不能, 为 FileChannel 装备非堵塞也没有含义。

运用Selector的长处:

运用更少的线程来就能够来处理通道了, 比较运用多个线程, 避免了线程上下文切换带来的开支。

1. 创立选择器

Selector selector = Selector.open();

2. 将通道注册到选择器上

ServerSocketChannel ssChannel = ServerSocketChannel.open();
ssChannel.configureBlocking(false);//通道有必要装备为非堵塞方式
ssChannel.register(selector, SelectionKey.OP_ACCEPT);

通道有必要装备为非堵塞方式,不然运用选择器就没有任何含义了,由于假如通道在某个事情上被堵塞,那么服务器就不能呼应其它事情,有必要等候这个事情处理完毕才干去处理其它事情,明显这和选择器的效果各走各路。

在将通道注册到选择器上时,还需求指定要注册的详细事情,首要有以下几类:

  • SelectionKey.OP_CONNECTSelectionKey.OP_ACCEPTSelectionKey.OP_READSelectionKey.OP_WRITE

它们在 SelectionKey 的界说如下:

public static final int OP_READ = 1 << 0;
public static final int OP_WRITE = 1 << 2;
public static final int OP_CONNECT = 1 << 3;
public static final int OP_ACCEPT = 1 << 4;

能够看出每个事情能够被当成一个位域,然后组成事情集整数。例如:

int interestSet = SelectionKey.OP_READ | SelectionKey.OP_WRITE;

3. 监听事情

int num = selector.sel蓬莱-Java面试必问通讯结构NIO,原理详解ect();

运用 select() 来监听抵达的事情,它会一向堵塞直到有至少一个事情抵达。

4. 获取抵达的事情

Set keys = selector.selectedKeys();
Iterator keyIterator = keys.iterator();
while (keyIterator.hasNext()) {
SelectionKey key = keyIterator.next();
if (key.isAcceptable()) {
// ...
} else if (key.isReadable()) {
// ...
}
keyIterator.remove();
}

5. 事情循环

由于一次 select() 调用不能处理完一切的事情,而且服务器端有或许需求一向监听事情,因而服务器端处理事情的代码一般会放在一个死循环内。

while (true) {
int num = selector.select();
Set keys = selector.selectedKeys();
Iterator keyIterator = keys.iterator();
while (keyIterator.hasNext()) {
SelectionKey key = keyIterator.next();
if (key.isAcceptable()) {
// ...
} else if (key.isReadable()) {
// ...
}
keyIterator.remove();
}
}

套接字 NIO 实例

public class NIOServer {
public static void main(String[] args) throws IOException {
//1. 创立选择器
Selector selector = Selector.open();
//2.将通道注册到选择器上
ServerSocketChannel ssChannel = ServerSocketChannel.open();
ssChannel.configureBlocking(false);
//通道有必要装备为非堵塞方式,不然运用选择器就没有任何含义了
ssChannel.register(selector, SelectionKey.OP_ACCEPT);
ServerSocket ss=ssChannel.socket();
ss.bind(new InetSocketAddress("127.0.0.1",8888));
while (true){
//3. 监听事情
selector.select();
//4. 获取抵达的事情
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 = ByteBuff补钙的食物有哪些er.allocate(1024);
StringBuilder data = new StringBuilder();
while (true) {
buffer.clear();
int r = sChannel.read(buffer);
if (r == -1) {
break;
}
buffer.flip();
int limit = buffer.limit();
char[] dst = new char[limit];
for (int i = 0; i < limit; i++) {
dst[i] = (char) buffer.get(i);蓬莱-Java面试必问通讯结构NIO,原理详解
}
data.append(dst);
buffer.clear();
}
return data.toString();
}
}
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";
out.write(s.getBytes());
out.close();
}
}

内存映射文件

内存映射文件 I/O 是一种读和写文件数据的办法,它能够比惯例的根据流或许根据通道的 I/O 快得多。

向内存映射文件写入或许是风险的,仅仅改动数组的单个元素这样的简略操作,就或许会直接修正磁盘上的文件。修正数据与将数据保存到磁盘是没有分隔的。

下面代码即将文件的前 1024 个字节映射到内存中,map() 办法回来一个 MappedByteBuffer,它是 ByteBuffer 的子类。因而,能够像运用其他任何 ByteBuffer 相同运用新映射的缓冲区,操作体系会在需求时担任履行映射。

MappedByteBuffer mbb = fc.map(FileChannel.MapMode.READ_WRITE, 0, 1024);

NIO与IO比照

NIO 与一般 I/O 的差异首要有以下三点:

  • NIO 对错堵塞的;NIO 面向块,I/O 面向流。NIO有选择器,而I/O没有。

Path

Java7中文件IO发生了很大的改变,专门引进了许多新的类来替代本来的 根据java.io.File的文件IO操作办法。

创立一个Path

运用Paths东西类的get()办法创立Path方针

public class PathDemo {
public static void main(String[] args) {
//办法一
Path path=Paths.get("demo5.txt");
System.out.println(path);
//办法二
Path path2 = FileSystems.getDefault().getPath("demo5.txt");
System.out.println(path2);
}
}

File和Path之间的转化,File和URI之间的转化

public class PathDemo2 {
public static void main(String[] args) {
Path path=Paths.get("demo5.txt");
File file=path.toFile();
URI uri=path.toUri();
System.out.println(path);
System.out.println(file);
System.out.println(uri);
}
}
demo5.txt
demo5.txt
file:///F:/Java_Review/05Java/JavaIO/demo5.txt

获取Path的相关信息

public class PathDemo3 {
public static void main(String[] args) {
Path path= Paths.get("demo3\\test3.txt");
System.out.println("文件名:"+ path.getFileName());
System.out.println("称号元素的数量:"+path.getNameCount());
System.out.println("父途径:"+ path.getParent());
System.out.println("根途径:"+ path.getRoot());
System.out.println("是否是绝对途径:"+path.isAbsolute());
//startWith() 参数既能够是字符串,也能够是Path
System.out.println("是否是以途径demo3最初:"+path.startsWith(Paths.get("demo3")));
System.out.println("该途径的字符串办法:"+path.toString());
}
}
文件名:test3.txt
称号元素的数量:2
父途径:demo3
根途径:null
是否是绝对途径:false
是否是以途径demo3最初:true
该途径的字符串办法:demo3\test3.txt

移除Path中的冗余项

\ .表明的是当时目录

\ ..表明父目录或许说是上一级目录

normalize() : 回来一个途径,该途径是取出冗余项的途径。

toRealPath() : 能够当作,先进行toAbsolutePath()操作,然后进行normalize()操作

public class PathDemo4 {
public static void main(String[] args) throws IOException {
Path path= Paths.get("./demo3");
System.out.println("original :"+ path.toAbsolutePath());
System.out.println("after normalize:"+ path.toAbsolutePath().normalize());
System.out.println("after toRealPath:"+ path.toRealPath());
}
}
original :F:\Java_Review\05Java\JavaIO\.\demo3
after normalize:F:\Java_Review\05Java\JavaIO\demo3
after toRealPath:F:\Java_Review\05Java\JavaIO\demo3
public class PathDemo5 {
public static void main(String[] args) throws IOException {
Path path= Paths.get("../JavaIO");
System.out.println("original :"+ path.toAbsolutePath());
System.out.println("after normalize:"+ path.toAbsolutePath().normalize());
System.out.println("after toRealPath:"+ path.toRealPath());
}
}
original :F:\Java_Review\05Java\JavaIO\..\JavaIO
after normalize:F:\Java_Review\05Java\JavaIO
after toRealPath:F:\Java_Review\05Java\JavaIO

Files

java.nio.file.Files类是和java.nio.file.Path相结合运用的

查看给定的Path在文件体系中是否存在

Files.exists():检测文件途径是否存在

public class FilesDemo {
public st蓬莱-Java面试必问通讯结构NIO,原理详解atic void main(String[] args) {
Path path = Paths.get("demo5.txt");
//LinkOptions.NOFOLLOW_LINKS:表明检测时不包括符号链接文件。
boolean isExist= Files.exists(path,new LinkOption[]{LinkOption.NOFOLLOW_LINKS});
System.out.println(isExist);
}
}

创立文件/文件夹

Files.createFile():创立文件

Files.createDirectory(): 创立文件夹

Files.createDirectories(): 创立文件夹

public class FilesDemo2 {
public static void main(String[] args) throws IOException {
Path path= Paths.get("demo7.txt");
if(!Files.exists(path)){
Files.createFile(path);
}
Path path2=Paths.get("demo4");
if(!Files.exists(path2)){
Files.createDirectory(path2);
}
Path path3=Paths.get("demo5\\test");
if(!Files.exists(path3)){
Files.createDirectories(path3);
}
}
}

删去文件或目录

Files.delete():删去一个文件或目录

public class FilesDemo3 {
public static void main(String[] args) throws IOException {
Path path= Paths.get("demo7.txt");
Files.delete(path);
}
}

把一个文件从一个地址仿制到另一个方位

Files.copy():把一个文件从一个地址仿制到另一个方位

public class FilesDemo4 {
public static void main(String[] args) throws IOException {
Path srcPath= Paths.get("demo6.txt");
Path destPath=Paths.get("demo7.txt");
//Files.copy(srcPath,destPath);
//强制掩盖现已存在的方针文件
Files.copy(srcPath,destPath, StandardCopyOption.REPLACE_EXISTING);
}
}

获取文件特点

public class FilesDemo5 {
public static void main(String[] args) throws IOException {
Path path= Paths.get("demo7.txt");
System.out.println(Files.getLastModifiedTime(path));
System.out.println(Files.size(path));
System.out.println(Files.isSymbolicLink(path));
System.out.println(Files.isDirectory(path));
System.out.println(Files.readAttributes(path,"*"));
}
}

遍历一个文件夹

public class FilesDemo6 {
public static void main(String[] args) throws IOException {
Path path= Paths.get("demo3\\demo2");
DirectoryStream paths=Files.newDirectoryStream(path);
for(Path p:paths){
System.out.println(p.getFileName());
}
}
}

遍历整个文件目录

FileVisitor需求调用方自行完成,然后作为参数传入walkFileTree(); FileVisitor的每个办法会在遍历进程中被调用屡次。

p蓬莱-Java面试必问通讯结构NIO,原理详解ublic class FilesDemo7 {
public static void main(String[] args) throws IOException {
Path path= Paths.get("demo3\\demo2");
List paths=new ArrayList<>();
Files.walkFileTree(path,new FileVisitor(paths));
System.out.println("paths:"+paths);
}
private static class FileVisitor extends SimpleFileVisitor {
private List paths;
public FileVisitor(List paths){
this.paths=paths;
}
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
if(file.toString().endsWith(".txt")){
paths.add(file.getFileName());
}
return super.visitFile(file, attrs);
}
}
}

输出成果:

paths:[a.txt, test2.txt, test.txt, test3.txt]

小编整理了免费Java高档材料,需求的自己收取,涵盖了Java、Redis、MongoDB、MySQL、Zookeeper、Spring Cloud、Dubbo高并发分布式等教程,总共30G。

私信回复“666”即可收取材料。

二维码