第一百八十三节 Java IO教程 - Java目录事件、Java异步I/O
Java IO教程 - Java目录事件
当文件系统中的对象被修改时,我们可以监听watch服务以获取警报。
java.nio.file包中的以下类和接口提供watch服务。
- Watchable接口
- WatchService接口
- WatchKey接口
- WatchEvent接口
- WatchEvent.Kind接口
- StandardWatchEventKinds类
可监视对象表示可以被监视的文件系统对象。可观看对象可以向手表服务注册。
Path对象是一个Watchable对象。
WatchService表示观察服务。当一个对象使用WatchService注册时,WatchService返回一个WatchKey作为注册的令牌。
WatchEvent表示注册到监视服务的对象上的事件。它的kind()方法返回发生的事件的类型。
它的context()方法返回一个Path对象,它表示事件发生的条目。
count()方法返回特定通知的事件发生次数。 如果它返回大于1的值,那么它是一个重复的事件。
WatchEvent.Kind <T>表示发生的事件的类型。
StandardWatchEventKinds类定义了用于表示事件种类的常量,如下所示。
- ENTRY_CREATE
- ENTRY_DELETE
- ENTRY_MODIFY
- OVERFLOW
OVERFLOW表示丢失或丢弃的事件。
创建观察服务以观察目录以进行更改。
WatchService ws = FileSystems.getDefault().newWatchService();
要使用Watch服务注册目录,使用register()方法,该方法将返回一个WatchKey对象作为注册令牌。
// Get a Path object for C:\myName directory to watch Path dirToWatch = Paths.get("C:\\myName"); WatchKey token = dirToWatch.register(ws, ENTRY_CREATE, ENTRY_MODIFY, ENTRY_DELETE);
要取消注册,请使用WatchKey的cancel()方法。
当注册目录时,其WatchKey处于就绪状态。
我们可以通过手表服务注册多个目录。
要从监视服务队列中检索WatchKey,使用WatchService对象的take()或poll()方法来检索和删除发出信号并排队的WatchKey。
take()方法等待,直到WatchKey可用。poll()方法允许我们为等待指定超时。
以下代码使用无限循环来检索发出信号的WatchKey。
while(true) {WatchKey key = ws.take(); }
处理事件
WatchKey的pollEvents()方法检索并删除所有挂起的事件。它返回一个WatchEvent的列表。 List的每个元素代表WatchKey上的一个事件。
以下代码显示了处理事件的典型逻辑:
while(true) {WatchKey key = ws.take();// Process all events of the WatchKey for(WatchEvent<?> event : key.pollEvents()) {// Process each event here} }
处理事件后重置WatchKey
我们需要重置WatchKey对象,通过调用其reset()方法来再次接收事件通知。
reset()方法将WatchKey置于就绪状态。如果WatchKey仍然有效,reset()方法返回true。 否则,它返回false。
如果WatchKey被取消或其监视服务关闭,它可能会失效。
// Reset the WatchKey boolean isKeyValid = key.reset(); if (!isKeyValid) {System.out.println("No longer watching " + dirToWatch); }
WatchService是可自动关闭的。我们可以在try-with-resources中创建一个WatchService的对象块,当程序退出块时它将自动关闭。
例子
以下代码显示了如何实现监视服务以监视目录中的更改。
import static java.nio.file.StandardWatchEventKinds.ENTRY_CREATE; import static java.nio.file.StandardWatchEventKinds.ENTRY_DELETE; import static java.nio.file.StandardWatchEventKinds.ENTRY_MODIFY; import static java.nio.file.StandardWatchEventKinds.OVERFLOW;import java.io.IOException; import java.nio.file.FileSystems; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.WatchEvent; import java.nio.file.WatchEvent.Kind; import java.nio.file.WatchKey; import java.nio.file.WatchService;public class Main {public static void main(String[] args) {try (WatchService ws = FileSystems.getDefault().newWatchService()) {Path dirToWatch = Paths.get("C:\\myName");dirToWatch.register(ws, ENTRY_CREATE, ENTRY_MODIFY, ENTRY_DELETE);while (true) {WatchKey key = ws.take();for (WatchEvent<?> event : key.pollEvents()) {Kind<?> eventKind = event.kind();if (eventKind == OVERFLOW) {System.out.println("Event overflow occurred");continue;}WatchEvent<Path> currEvent = (WatchEvent<Path>) event;Path dirEntry = currEvent.context();System.out.println(eventKind + " occurred on " + dirEntry);}boolean isKeyValid = key.reset();if (!isKeyValid) {System.out.println("No longer watching " + dirToWatch);break;}}} catch (IOException | InterruptedException e) {e.printStackTrace();}} }
Java IO教程 - Java异步I/O
在同步文件I/O中,对I/O操作的请求将等待,直到I/O操作完成。
在异步文件I/O中,I/O操作的请求由系统异步执行。
当系统完成文件I/O时,它通知应用程序其请求的完成。
java.nio.channels.AsynchronousFileChannel类表示异步文件通道。
AsynchronousFileChannel类的静态open()方法获取AsynchronousFileChannel类的实例。
以下代码显示了如何获取WRITE的异步文件通道。
Path path = Paths.get("C:\\Java_Dev\\rainbow.txt"); AsynchronousFileChannel afc = AsynchronousFileChannel.open(path, WRITE, CREATE);
AsynchronousFileChannel提供了两种方法来处理异步文件I/O操作的结果。
- Using a java.util.concurrent.Future object.
- Using a java.nio.channels.CompletionHandler object.
支持异步文件I/O操作的AsynchronousFileChannel类的每个方法有两个版本。
一个版本返回一个Future对象,我们可以使用它来处理所请求的异步操作的结果。
Future对象的get()方法返回写入文件通道的字节数。
以下代码使用返回Future对象的write()方法的版本:
ByteBuffer dataBuffer = a buffer; long startPosition = 0; Future<Integer> result = afc.write(dataBuffer, startPosition);
一旦我们得到一个Future对象,我们可以使用轮询方法或阻塞等待方法来处理异步文件I/O的结果。
下面的代码显示了轮询方法,它将继续调用Future对象的isDone()方法,以检查I/O操作是否完成:
while (!result.isDone()) { } int writtenNumberOfBytes = result.get();
AsynchronousFileChannel类的另一个版本的方法获得一个CompletionHandler对象,当请求的异步I/O操作完成或失败时,该对象的方法被调用。
CompletionHandler接口有两个方法:completed()和failed()。
当所请求的I/O操作成功完成时,将调用completed()方法。
当请求的I/O操作时失败,则调用failed()方法。
以下代码使用Attachment类的对象作为完成处理程序的附件:
class Attachment {public Path path;public ByteBuffer buffer;public AsynchronousFileChannel asyncChannel; } class MyHandler implements CompletionHandler<Integer, Attachment> {@Overridepublic void completed(Integer result, Attachment attach) {// Handle completion of the I/O operation}@Overridepublic void failed(Throwable e, Attachment attach) {// Handle failure of the I/O operation} }
以下代码使用MyHandler实例作为异步写操作的完成处理程序。
MyHandler handler = new MyHandler(); ByteBuffer dataBuffer = get a data buffer; Attachment attach = new Attachment(); attach.asyncChannel = afc; attach.buffer = dataBuffer; attach.path = path;// Perform the asynchronous write operation afc.write(dataBuffer, 0, attach, handler);
以下代码演示了如何使用CompletionHandler对象来处理对文件的异步写入的结果。
import static java.nio.file.StandardOpenOption.CREATE; import static java.nio.file.StandardOpenOption.WRITE;import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.AsynchronousFileChannel; import java.nio.channels.CompletionHandler; import java.nio.charset.Charset; import java.nio.file.Path; import java.nio.file.Paths; public class Main {public static void main(String[] args) throws Exception {Path path = Paths.get("test.txt");AsynchronousFileChannel afc = AsynchronousFileChannel.open(path, WRITE,CREATE);WriteHandler handler = new WriteHandler();ByteBuffer dataBuffer = getDataBuffer();Attachment attach = new Attachment();attach.asyncChannel = afc;attach.buffer = dataBuffer;attach.path = path;afc.write(dataBuffer, 0, attach, handler);System.out.println("Sleeping for 5 seconds...");Thread.sleep(5000);}public static ByteBuffer getDataBuffer() {String lineSeparator = System.getProperty("line.separator");StringBuilder sb = new StringBuilder();sb.append("test");sb.append(lineSeparator);sb.append("test");sb.append(lineSeparator);String str = sb.toString();Charset cs = Charset.forName("UTF-8");ByteBuffer bb = ByteBuffer.wrap(str.getBytes(cs));return bb;} } class Attachment {public Path path;public ByteBuffer buffer;public AsynchronousFileChannel asyncChannel; }class WriteHandler implements CompletionHandler<Integer, Attachment> {@Overridepublic void completed(Integer result, Attachment attach) {System.out.format("%s bytes written to %s%n", result,attach.path.toAbsolutePath());try {attach.asyncChannel.close();} catch (IOException e) {e.printStackTrace();}}@Overridepublic void failed(Throwable e, Attachment attach) {try {attach.asyncChannel.close();} catch (IOException e1) {e1.printStackTrace();}} }
例子
以下代码演示了如何使用Future对象来处理对文件的异步写入的结果。
import static java.nio.file.StandardOpenOption.CREATE; import static java.nio.file.StandardOpenOption.WRITE;import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.AsynchronousFileChannel; import java.nio.charset.Charset; import java.nio.file.Path; import java.nio.file.Paths; import java.util.concurrent.Future;public class Main {public static ByteBuffer getDataBuffer() {String lineSeparator = System.getProperty("line.separator");StringBuilder sb = new StringBuilder();sb.append("test");sb.append(lineSeparator);String str = sb.toString();Charset cs = Charset.forName("UTF-8");ByteBuffer bb = ByteBuffer.wrap(str.getBytes(cs));return bb;}public static void main(String[] args) throws Exception {Path path = Paths.get("test.txt");try (AsynchronousFileChannel afc = AsynchronousFileChannel.open(path,WRITE, CREATE)) {ByteBuffer dataBuffer = getDataBuffer();Future<Integer> result = afc.write(dataBuffer, 0);while (!result.isDone()) {System.out.println("Sleeping for 2 seconds...");Thread.sleep(2000);}int writtenBytes = result.get();System.out.format("%s bytes written to %s%n", writtenBytes,path.toAbsolutePath());} catch (IOException e) {e.printStackTrace();}} }
上面的代码生成以下结果。
例2
以下代码演示了如何使用CompletionHandler对象来处理从文件进行异步读取的结果。
import static java.nio.file.StandardOpenOption.READ;import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.AsynchronousFileChannel; import java.nio.channels.CompletionHandler; import java.nio.charset.Charset; import java.nio.file.Path; import java.nio.file.Paths; public class Main {public static void main(String[] args) throws Exception{Path path = Paths.get("test.txt");AsynchronousFileChannel afc = AsynchronousFileChannel.open(path, READ);ReadHandler handler = new ReadHandler();int fileSize = (int) afc.size();ByteBuffer dataBuffer = ByteBuffer.allocate(fileSize);Attachment attach = new Attachment();attach.asyncChannel = afc;attach.buffer = dataBuffer;attach.path = path;afc.read(dataBuffer, 0, attach, handler);System.out.println("Sleeping for 5 seconds...");Thread.sleep(5000);} } class Attachment {public Path path;public ByteBuffer buffer;public AsynchronousFileChannel asyncChannel; }class ReadHandler implements CompletionHandler<Integer, Attachment> {@Overridepublic void completed(Integer result, Attachment attach) {System.out.format("%s bytes read from %s%n", result, attach.path);System.out.format("Read data is:%n");byte[] byteData = attach.buffer.array();Charset cs = Charset.forName("UTF-8");String data = new String(byteData, cs);System.out.println(data);try {// Close the channelattach.asyncChannel.close();} catch (IOException e) {e.printStackTrace();}}@Overridepublic void failed(Throwable e, Attachment attach) {System.out.format("Read operation on %s file failed."+ "The error is: %s%n", attach.path, e.getMessage());try {// Close the channelattach.asyncChannel.close();} catch (IOException e1) {e1.printStackTrace();}} }
上面的代码生成以下结果。
例3
以下代码显示了如何使用Future对象来处理从文件进行异步读取的结果。它使用等待方法(Future.get()方法调用)等待异步文件I/O完成。
import static java.nio.file.StandardOpenOption.READ;import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.AsynchronousFileChannel; import java.nio.charset.Charset; import java.nio.file.Path; import java.nio.file.Paths; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future;public class Main {public static void main(String[] args) throws Exception {Path path = Paths.get("test.txt");try (AsynchronousFileChannel afc = AsynchronousFileChannel.open(path, READ)) {int fileSize = (int) afc.size();ByteBuffer dataBuffer = ByteBuffer.allocate(fileSize);Future<Integer> result = afc.read(dataBuffer, 0);int readBytes = result.get();System.out.format("%s bytes read from %s%n", readBytes, path);System.out.format("Read data is:%n");byte[] byteData = dataBuffer.array();Charset cs = Charset.forName("UTF-8");String data = new String(byteData, cs);System.out.println(data);} catch (IOException ex) {ex.printStackTrace();}} }
上面的代码生成以下结果。
相关文章:

第一百八十三节 Java IO教程 - Java目录事件、Java异步I/O
Java IO教程 - Java目录事件 当文件系统中的对象被修改时,我们可以监听watch服务以获取警报。 java.nio.file包中的以下类和接口提供watch服务。 Watchable接口WatchService接口WatchKey接口WatchEvent接口WatchEvent.Kind接口StandardWatchEventKinds类 可监视对…...

【设计模式】(万字总结)深入理解Java中的创建型设计模式
1. 前言 在软件开发的世界里,设计模式是一种被广泛接受并应用的解决方案。它们不仅仅是代码的设计,更是对问题的思考和解决的方法论。在Java开发中,特别是在面向对象的编程中,设计模式尤为重要。创建型设计模式,作为设…...

【全面讲解下Docker in Docker的原理与实践】
🌈个人主页: 程序员不想敲代码啊 🏆CSDN优质创作者,CSDN实力新星,CSDN博客专家 👍点赞⭐评论⭐收藏 🤝希望本文对您有所裨益,如有不足之处,欢迎在评论区提出指正,让我们共同学习、交流进步! 👉目录 👉前言👉原理👉实践👉安全和最佳实践👉前言 🦛…...
Android Settings增加多击事件,增加开发者模式打开难度
软件平台:Android11 硬件平台:QCS6125 需求来源:用户通过系统异常崩溃,进入原生Settings页面,通过默认的多击版本号方式打开开发者模式,继而打开adb调试开关,安装三方apk。 对付这种需求本来有…...

【相机与图像】1. 相机模型的介绍:内参、外参、畸变参数
想着整理下相机模型(内容上参考 slam十四讲)、相机的内外参标定。方便自己的使用和回顾。 不过,内外参标定啥时候记录随缘 -_- 概述 【构建相机模型】 相机将三位世界中的坐标点(单位为米)映射到二维图像平面ÿ…...

Linux内核netlink机制 - 用户空间和内核空间数据传输
简介: Netlink socket 是一种Linux特有的socket,用于实现用户空间与内核空间通信的一种特殊的进程间通信方式(IPC) ,也是网络应用程序与内核通信的最常用的接口。 Netlink 是一种在内核和用户应用间进行双向数据传输的非常好的方式&a…...

Node.js自动化处理TOML文件
在软件开发过程中,自动化处理配置文件是一种常见的需求。TOML(Tom’s Obvious, Minimal Language)是一种用于配置文件的简单易读的格式。本文将展示如何使用Node.js和一些流行的库来自动化读取、修改并写入TOML文件。 1. 准备工作 在开始之前…...

Spring boot 后端向前端发送日期时间发现少了8小时
问题 数据库 后端的控制台输出 前端控制台输出 可以发现少了8小时 问题 springboot 向前端响应数据是默认 Json 格式,所以会有类型转换,springboot 就通过 Jackson 来对 data 类型数据进行转换,但是Jackson 类型的时区是 GMT,与…...

MySQL数据库(基础篇)
🌏个人博客主页:心.c 前言:今天讲解的是MySQL的详细知识点的,希望大家可以收货满满,话不多说,直接开始搞! 🔥🔥🔥文章专题:MySQL 😽感…...

ffmpeg ffplay.c 源码分析二:数据读取线程
本章主要是分析 数据读取线程read_thread 中的工作。如上图红色框框的部分 从ffplay框架分析我们可以看到,ffplay有专⻔的线程read_thread()读取数据, 且在调⽤av_read_frame 读取数据包之前需要做: 1.例如打开⽂件, 2.查找配置解…...

国科大作业考试资料《人工智能原理与算法》2024新编-第十三次作业整理
1、假设我们从决策树生成了一个训练集,然后将决策树学习应用于该训练集。当训练集的大小趋于无穷时,学习算法将最终返回正确的决策树吗?为什么是或不是? 本次有两个参考: 参考一: 当训练集的大小趋于无穷…...

Netdevops入门之Telnetlib语法案例
1、Telnetlib模块: 支持telnet/ssh远程访问的模块很多,常见的有telnetlib、ciscolib、paramiko、netmiko、pexpect,其中telnetlib和ciscolib对应telnet协议,后面3个对应SSH协议。 ①-通过ENSP环境搭建实验环境 ②-基础语法-telnetlib案例1&…...
永辉“爆改”续命
2024年,在线下零售一片哀嚎之下,胖东来似乎活成了国内零售业的密码,同时也变身成为各大零售企业的咨询公司,四处帮助“友商”救火,就连一直名声在外的永辉超市,也成了救火对象。 作为曾经国内生鲜超市的“…...

IEEE双一区Top“饱受诟病”!曾上医院黑名单,国人占比高达82.405%,目测即将拉下神坛?
本周投稿推荐 SCI&EI • 1区计算机类,3.5-4.0(1个月录用) • CCF推荐,1区-Top(3天初审) EI • 各领域沾边均可(2天录用) 知网(CNKI)、谷歌学术 •…...

Hive环境搭建(Mysql数据库)
【实验目的】 1) 了解hive的作用 2) 熟练hive的配置过程(Mysql数据库) 【实验原理】 Hive工具中默认使用的是derby数据库,该数据库使用简单,操作灵活,但是存在一定的局限性,hive支持使用第三方数据库&…...

【ESP32 IDF SPI硬件驱动W25Q64】
目录 SPISPI介绍idf配置初始化配置通信 驱动代码 SPI SPI介绍 详细SPI介绍内容参考我之前写的内容【ESP32 IDF 软件模拟SPI驱动 W25Q64存储与读取数组】 idf配置 初始化配置 spi_bus_initialize() 参数1 :spi几,例如spi2,spi3 参数2:…...

太原高校大学智能制造实验室数字孪生可视化系统平台建设项目验收
随着科技的不断进步,智能制造已经成为推动制造业转型升级的重要力量。太原高校大学智能制造实验室紧跟时代步伐,积极推进数字孪生可视化系统平台的建设,并于近日圆满完成了项目的验收工作。这一里程碑式的成果,不仅标志着实验室在…...

Kafka消息队列
目录 什么是消息队列 高可用性 高扩展性 高可用性 持久化和过期策略 consumer group 分组消费 ZooKeeper 什么是消息队列 普通版消息队列 说白了就是一个队列,生产者生产多少,放在消息队列中存储,而消费者想要多少拿多少,按序列号消费 缓存信息 生产者与消费者解耦…...
@Transactional注解及其事务管理
1. 事务问题概述 事务问题主要来源于数据库,与数据库事务紧密相关。事务的四大特性(ACID): 原子性(Atomicity):事务要么完全执行,要么完全不执行。一致性(Consistency&a…...
ROS2入门到精通—— 3-1 ROS2实战:CasADi —— 优化计算的利器
0 前言 CasADi是一个强大的开源软件库,它提供了一种灵活且高效的方式来构建和解决复杂的非线性模型。通过其直观的API,开发者可以轻松地定义数学表达式并自动求解微分方程、优化问题以及符号计算等任务。 CasADi基于Python编写,但提供了C++和MATLAB接口,使得不同背景的开发…...

业务系统对接大模型的基础方案:架构设计与关键步骤
业务系统对接大模型:架构设计与关键步骤 在当今数字化转型的浪潮中,大语言模型(LLM)已成为企业提升业务效率和创新能力的关键技术之一。将大模型集成到业务系统中,不仅可以优化用户体验,还能为业务决策提供…...
FastAPI 教程:从入门到实践
FastAPI 是一个现代、快速(高性能)的 Web 框架,用于构建 API,支持 Python 3.6。它基于标准 Python 类型提示,易于学习且功能强大。以下是一个完整的 FastAPI 入门教程,涵盖从环境搭建到创建并运行一个简单的…...

YSYX学习记录(八)
C语言,练习0: 先创建一个文件夹,我用的是物理机: 安装build-essential 练习1: 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件,随机修改或删除一部分,之后…...

基于当前项目通过npm包形式暴露公共组件
1.package.sjon文件配置 其中xh-flowable就是暴露出去的npm包名 2.创建tpyes文件夹,并新增内容 3.创建package文件夹...

转转集团旗下首家二手多品类循环仓店“超级转转”开业
6月9日,国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解,“超级…...

微服务商城-商品微服务
数据表 CREATE TABLE product (id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 商品id,cateid smallint(6) UNSIGNED NOT NULL DEFAULT 0 COMMENT 类别Id,name varchar(100) NOT NULL DEFAULT COMMENT 商品名称,subtitle varchar(200) NOT NULL DEFAULT COMMENT 商…...

【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)
骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术,它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton):由层级结构的骨头组成,类似于人体骨骼蒙皮 (Mesh Skinning):将模型网格顶点绑定到骨骼上,使骨骼移动…...

k8s业务程序联调工具-KtConnect
概述 原理 工具作用是建立了一个从本地到集群的单向VPN,根据VPN原理,打通两个内网必然需要借助一个公共中继节点,ktconnect工具巧妙的利用k8s原生的portforward能力,简化了建立连接的过程,apiserver间接起到了中继节…...
OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别
OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别 直接训练提示词嵌入向量的核心区别 您提到的代码: prompt_embedding = initial_embedding.clone().requires_grad_(True) optimizer = torch.optim.Adam([prompt_embedding...
OpenLayers 分屏对比(地图联动)
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 地图分屏对比在WebGIS开发中是很常见的功能,和卷帘图层不一样的是,分屏对比是在各个地图中添加相同或者不同的图层进行对比查看。…...