从零开始学习Netty - 学习笔记 - NIO基础 - 文件编程:FileChannel,Path,Files

3.文件编程

3.1.FileChannel

FileChannel只能工作在非阻塞模式下面,不能和selector一起使用

获取

不能直接打开FIleChannel,必须通过FileInputSream,或者FileOutputSetream ,或者RandomAccessFile来获取FileChannel

  • 通过FileInputSream获取的channel只能
  • 通过FileOutputSetream 获取的channel只能
  • 通过RandomAccessFile 是否能读写,根据构造时指定的读写模式相关(“r”,“w”)
读取

会从channel读取数据填充到ByteBuffer中,返回的值,表示读到了多少字节,-1表示到达了文件的末尾

int read = channel.read(buffer);
写入

在while中调用 write方法,是因为 write方法并不能保证一次将buffer中的内容全部写入channel中

public void test4(){try (FileChannel channel = new RandomAccessFile("data.txt", "rw").getChannel()) {ByteBuffer b = ByteBuffer.allocate(10);b.put((byte) 'a');  // 存入数据b.put((byte) 'b');  // 存入数据b.put((byte) 'c');  // 存入数据b.flip(); // 切换为读模式// 在while中调用 write方法,是因为 write方法并不能保证一次将buffer中的内容全部写入channel中while (b.hasRemaining()){// 写入数据channel.write(b);}} catch (IOException e) {}
}

在这里插入图片描述

关闭

channel必须关闭,不过调用了FileInoutStreamFileOutputStream,或者RandomAccessFileclose方法会间接的调用channle的close方法

位置

channel.position 是 Java NIO 中用于获取通道(Channel)当前的位置的方法。通道的位置表示从数据源(如文件或网络连接)的开头到当前位置之间的字节数。

@Test
@DisplayName("测试channel.position()方法")
public void test5(){try (FileChannel channel = new RandomAccessFile("data.txt", "r").getChannel()) {// 获取当前通道的位置ByteBuffer buffer = ByteBuffer.allocate(10);buffer.put((byte) 'a');buffer.put((byte) 'a');buffer.put((byte) 'a');// 切换为读模式buffer.flip();channel.read(buffer);long position = channel.position();logger.error("Current position: {}", position);// 在文件中移动位置,假设移动到文件的开头channel.position(0);// 再次获取当前通道的位置position = channel.position();logger.error("Current position: {}", position);} catch (IOException e) {e.printStackTrace();}
}

在这里插入图片描述

  • channel.position() 返回当前通道的位置。
  • channel.position(0) 将通道的位置移动到文件的开头。
  • 通过调用 position() 方法,你可以控制从文件的哪个位置读取数据,或者从哪个位置开始写入
大小

使用size可以获取文件的大小

long size = channel.size();
强制写入

强制写入操作可以看作是将缓冲区中的数据内容直接写入到磁盘上,而不依赖于操作系统的延迟写入策略(因为出于性能考虑,操作系统会将数据进行缓存,而不是立刻写入磁盘)。这样可以保证写入数据的即时性和持久性,但同时也会增加写入操作的开销和系统的负载。

// 假设 channel 是一个 FileChannel 对象
channel.force(true); // 执行强制写入操作

3.2.两个Channel之间传递数据

transferTo() 方法是 Java NIO 中的一个用于通道之间数据传输的方法。这个方法允许将数据从一个通道直接传输到另一个通道,而不需要中间缓冲区。

在Java NIO中,数据可以在通道之间直接传输,而不必经过缓冲区。这种直接传输的方式在大数据量传输时能够提高性能并降低内存消耗。

transferTo() 方法通常用于将一个通道的数据传输到另一个通道,例如将一个文件通道的内容传输到网络套接字通道,或者将一个输入流传输到输出流。

零拷贝transferTo()底层就是使用了零拷贝进行优化

  1. 当调用 transferTo() 方法时,底层操作系统会尝试将数据直接从源通道传输到目标通道,而不需要经过用户空间的缓冲区。
  2. 操作系统会使用DMA(直接内存访问)技术,从源文件的内核缓冲区中直接读取数据,并将数据直接写入目标文件的内核缓冲区中。
  3. 这样,数据不需要经过用户空间的缓冲区,也不需要额外的数据复制操作,从而实现了零拷贝的数据传输
	@Test@DisplayName("两个Channel之间传递数据")public void test6(){try(FileChannel FROM = new FileInputStream("data.txt").getChannel();FileChannel TO = new FileOutputStream("data2.txt").getChannel();) {// 1.从FROM中读取数据 TO中写入数据 但是最大只能传输2G// 2.left变量表示还剩余多少字节没有传输long size = FROM.size();for (long left = size; left > 0;){// 每次传输的字节大小 会返回long l = FROM.transferTo((size-left), left, TO);// 3.每次传输完毕后,更新left的值left -= l;}} catch (IOException e) {e.printStackTrace();}}

3.3.Path

JDK 7 以后引入 Path 和 Paths两个类

  • **Path:**用来表示文件的路径

    • 创建路径

      • Paths.get(String first, String... more):创建路径实例。
      • Path resolve(String other):解析相对路径。
    • 获取路径信息

      • Path getFileName():获取路径中的文件名部分。
      • Path getParent():获取路径中的父路径部分。
      • int getNameCount():获取路径的名称元素数量。
      • Path getName(int index):获取路径中指定索引位置的名称元素。
    • 判断路径属性

      • boolean isAbsolute():判断路径是否为绝对路径。
      • boolean startsWith(String other) / boolean endsWith(String other):判断路径是否以指定字符串开始或结束。
    • 转换路径

      • Path toAbsolutePath():将路径转换为绝对路径。
      • Path relativize(Path other):获取当前路径相对于另一路径的相对路径。
    • 比较路径

      • int compareTo(Path other):比较两个路径的字典顺序。
    • 判断文件系统操作

      • boolean exists():判断路径所代表的文件或目录是否存在。
      • boolean isRegularFile() / boolean isDirectory():判断路径表示的是否为普通文件或目录。
      • boolean isReadable() / boolean isWritable() / boolean isExecutable():判断文件是否可读、可写、可执行。
    • 操作路径

      • Path normalize():规范化路径,解析 ... 等符号。
      • Path resolveSibling(Path other):返回当前路径的父路径与给定路径的相对路径组合而成的路径。
      • void createDirectory():创建一个目录。
      • void createFile():创建一个文件。
    • 遍历目录

      • DirectoryStream<Path> newDirectoryStream(Path dir):返回目录中的条目的目录流。
    • 读取文件内容

      • byte[] readAllBytes():读取文件的所有字节并返回一个字节数组。
      • List<String> readAllLines():读取文件的所有行并返回一个字符串列表。
    • 删除文件或目录

    • boolean deleteIfExists():删除指定的文件或目录。

  • **Paths:**是工具类,用来获取Path的实例

// 相对路径,根据user.dir 环江变量来定位 data.txt
Path path = Paths.get("data.txt");
logger.error("path: {}", path.toAbsolutePath());// 绝对路径
Paths.get("D:\\dcjet\\java_base_study\\data.txt");
logger.error("path: {}", path.toAbsolutePath());// 绝对路径
Paths.get("D:/dcjet/java_base_study/data.txt");
logger.error("path: {}", path.toAbsolutePath());// 绝对路径
Paths.get("D:\\dcjet\\java_base_study\\", "data.txt");
logger.error("path: {}", path.toAbsolutePath());

在这里插入图片描述

... 是用于表示目录结构中的当前目录和父目录的特殊符号。

  • .:表示当前目录,即当前所在位置的目录。
  • ..:表示父目录,即当前目录的上一级目录。
root/├── documents/│   ├── file1.txt├── pictures/└── videos/

documents 目录中,. 表示 documents 目录本身,.. 表示 root 目录

3.4.Files

  1. 复制文件或目录

    Path source = Paths.get("source.txt");
    Path target = Paths.get("target.txt");
    Files.copy(source, target, StandardCopyOption.REPLACE_EXISTING);
    
  2. 移动文件或目录

    Path source = Paths.get("source.txt");
    Path target = Paths.get("target.txt");
    Files.move(source, target, StandardCopyOption.REPLACE_EXISTING);
    
  3. 删除文件或目录

    Path path = Paths.get("file.txt");
    // 如果目录还有文件 会有报错
    // 如果删除的目录 不存在 也会报错
    Files.delete(path);
    
  4. 创建文件或目录

    // 可以创建多级目录
    Path dir = Paths.get("test/d1/d2");
    // 只能创建一级目录
    Files.createDirectory(dir);
    // 创建多级目录
    Files.createDirectories(dir);
    
  5. 读取文件内容

    Path path = Paths.get("file.txt");
    byte[] bytes = Files.readAllBytes(path);
    
  6. 写入文件内容

    Path path = Paths.get("file.txt");
    List<String> lines = Arrays.asList("Hello", "World");
    Files.write(path, lines, StandardCharsets.UTF_8);
    
  7. 判断文件或目录属性

    Path path = Paths.get("file.txt");
    boolean exists = Files.exists(path);
    boolean isRegularFile = Files.isRegularFile(path);
    
  8. 比较文件内容

    Path path1 = Paths.get("file1.txt");
    Path path2 = Paths.get("file2.txt");
    boolean isSameFile = Files.isSameFile(path1, path2);
    
  9. 获取文件或目录属性

    Path path = Paths.get("file.txt");
    FileStore fileStore = Files.getFileStore(path);
    
  10. 遍历目录

    Path dir = Paths.get("directory");
    try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir)) {for (Path entry : stream) {System.out.println(entry.getFileName());}
    } catch (IOException e) {e.printStackTrace();
    }
    
  11. 其他操作

    遍历文件夹

    @Test
    @DisplayName("遍历文件夹")
    public void test8() {Path path = Paths.get("D:\\dcjet\\java_base_study\\src\\main\\java\\com\\hrfan\\java_se_base\\netty\\nio");try {// 遍历文件夹(访问者模式应用)Files.walkFileTree(path, new SimpleFileVisitor<Path>() {@Overridepublic FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {// 遍历之前logger.error("file: {}", file);return FileVisitResult.CONTINUE;}});} catch (IOException e) {e.printStackTrace();}
    }
    
    • 在这里插入图片描述

      删除多级目录

      在这个案例中使用 Files.walkFileTree() 方法遍历了目录树,并在 visitFile() 方法中删除了每个文件,在 postVisitDirectory() 方法中删除了每个目录。注意,删除操作会递归删除目录中的所有文件和子目录。

      @Test
      @DisplayName("删除目录")
      public void test9() {AtomicInteger atomicInteger = new AtomicInteger(0);Path path = Paths.get("D:\\aa\\adsa");try {// 遍历文件夹Files.walkFileTree(path, new SimpleFileVisitor<Path>() {@Overridepublic FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {Files.delete(file); // 删除文件logger.error("delete file: {}", file);return FileVisitResult.CONTINUE;}@Overridepublic FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {// 删除目录(退出时删除目录因为此时目录中没有文件了)Files.delete(dir);logger.error("delete dir: {}", dir);return super.postVisitDirectory(dir, exc);}});// 最终遍历完成logger.error("get file number: {}", atomicInteger.get());} catch (IOException e) {e.printStackTrace();}
      }
      

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/694724.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

互联网高科技公司领导AI工业化,MatrixGo加速人工智能落地

作者&#xff1a;吴宁川 AI&#xff08;人工智能&#xff09;工业化与AI工程化正在引领人工智能的大趋势。AI工程化主要从企业CIO角度&#xff0c;着眼于在企业生产环境中规模化落地AI应用的工程化举措&#xff1b;而AI工业化则从AI供应商的角度&#xff0c;着眼于以规模化方式…

Rust ?运算符 Rust读写txt文件

一、Rust &#xff1f;运算符 &#xff1f;运算符&#xff1a;传播错误的一种快捷方式。 如果Result是Ok&#xff1a;Ok中的值就是表达式的结果&#xff0c;然后继续执行程序。 如果Result是Err&#xff1a;Err就是整个函数的返回值&#xff0c;就像使用了return &#xff…

电脑wifi丢失修复

当你打开电脑突然发现wifi功能不见了&#xff0c;可以先查看一下网卡的状态 在控制面板中找到设备管理器&#xff0c;打开就能找到网络适配器&#xff0c; 我这里是修复过的&#xff0c;wifi丢失后这里可能会显示WALN是丢失的&#xff0c;其他项显示黄色感叹号。 如何修复呢…

Go语言中的TLS加密:深入crypto/tls库的实战指南

Go语言中的TLS加密&#xff1a;深入crypto/tls库的实战指南 引言crypto/tls库的核心组件TLS配置&#xff1a;tls.Config证书加载与管理TLS握手过程及其实现 构建安全的服务端创建TLS加密的HTTP服务器配置TLS属性常见的安全设置和最佳实践 开发TLS客户端应用编写使用TLS的客户端…

[游戏开发][虚幻5]新建项目注意事项

鼠标右键点击Client.uproject文件&#xff0c;可以看到三个比较关键的选项&#xff0c; 启动游戏&#xff0c;生成sln解决方案&#xff0c;切换引擎版本 断点调试 C代码重要步骤 如果你想断点调试C代码&#xff0c;则必须使用使用代码编译启动引擎&#xff0c;你需要做几个操作…

从零开始学习Netty - 学习笔记 - NIO基础 - 网络编程: Selector

4.网络编程 4.1.非阻塞 VS 阻塞 在网络编程中&#xff0c;**阻塞&#xff08;Blocking&#xff09;和非阻塞&#xff08;Non-blocking&#xff09;**是两种不同的编程模型&#xff0c;描述了程序在进行网络通信时的行为方式。 阻塞&#xff08;Blocking&#xff09;&#xff1…

js设计模式:计算属性模式

作用: 将对象中的某些值与其他值进行关联,根据其他值来计算该值的结果 vue中的计算属性就是很经典的例子 示例: let nowDate 2023const wjtInfo {brithDate:1995,get age(){return nowDate-this.brithDate}}console.log(wjtInfo.age,wjt年龄)nowDate 1console.log(wjtInf…

【算法与数据结构】1020、130、LeetCode飞地的数量 被围绕的区域

文章目录 一、1020、飞地的数量二、130、被围绕的区域三、完整代码 所有的LeetCode题解索引&#xff0c;可以看这篇文章——【算法和数据结构】LeetCode题解。 一、1020、飞地的数量 思路分析&#xff1a;博主认为题目很抽象&#xff0c;非常难理解。想了好久&#xff0c;要理解…

【蝶变跃升】壹起来|就业辅导系列活动——职业生涯规划和模拟面试

为使困难家庭更深层次了解自己就业现状&#xff0c;明确就业方向&#xff0c;同时提升在面试时的各类技巧。2024年2月17日&#xff0c;由平湖市民政局主办、平湖吾悦广场和上海聘也科技有限公司协办、平湖市壹起来公益发展中心承办的“蝶变跃升”就业辅导系列——职业生涯规划和…

2024新版Java高频面试题+Java八股文面试真题

Java面试题_2024新版Java高频面试题Java八股文面试真题 Java高频面试专题视频课程&#xff0c;瓤括了Java生态下的主流技术面试题&#xff0c;课程特色&#xff1a; 1、全面&#xff0c;jvm、并发编程、mysql、rabbitmq、spring、mybatis、redis、分布式、微服务、数据结构等等…

Flutter学习4 - Dart数据类型

1、基本数据类型 num、int、double &#xff08;1&#xff09;常用数据类型 num类型&#xff0c;是数字类型的父类型&#xff0c;有两个子类 int 和 double 通过在函数名前加下划线&#xff0c;可以将函数变成私有函数&#xff0c;私有函数只能在当前文件中调用 //常用数据…

docker之安装mongo创建运行环境

目录 一、docker pull 最新资源 二、启动mongo镜像 启动命令查看日志拉取低版本镜像成功启动 三、进入mongo容器 进入容器进入mongo环境查询当前所在库切换库至admin随意切换库 并 创建用户登录用户新增文档数据等 五、总结 版本兼容可备份操作 一、docker pull 最新资源…

顺序表详解(如何实现顺序表)

文章目录 前言 在进入顺序表前&#xff0c;我们先要明白&#xff0c;数据结构的基本概念。 一、数据结构的基本概念 1.1什么是数据结构 数据结构是由“数据”和“结构”两词组合而来。所谓数据就是&#xff1f;常见的数值1、2、3、4.....、姓名、性别、年龄&#xff0c;等。…

开发一款招聘小程序需要具备哪些功能?

随着时代的发展&#xff0c;找工作的方式也在不断变得简单&#xff0c;去劳务市场、人才市场的方式早就已经过时了&#xff0c;现在大多数年轻人都是直接通过手机来找工作。图片 找工作类的平台不但能扩大企业的招聘渠道&#xff0c;还能节省招聘的成本&#xff0c;方便求职者进…

C# 使用onnxruntime部署夜间雾霾图像的可见度增强

目录 介绍 模型信息 效果 项目 代码 下载 C# Onnx 使用onnxruntime部署夜间雾霾图像的可见度增强 介绍 github地址&#xff1a;GitHub - jinyeying/nighttime_dehaze: [ACMMM2023] "Enhancing Visibility in Nighttime Haze Images Using Guided APSF and Gradien…

如何修改unity的背景颜色

要在Unity中将背景颜色设为黑色&#xff0c;可以按照以下步骤进行&#xff1a; 1、在Unity编辑器中&#xff0c;选择你想要修改背景颜色的摄像机对象&#xff08;一般是Main Camera&#xff09;。 2、在Inspector面板中&#xff0c;找到"Clear Flags"&#xff08;清…

ChatGPT 4.0 升级指南

1.ChatGPT 是什么&#xff1f; ChatGPT 是由 OpenAI 开发的一种基于人工智能的聊天机器人&#xff0c;它基于强大的语言处理模型 GPT&#xff08;Generative Pre-trained Transformer&#xff09;构建。它能够理解人类语言&#xff0c;可以为我们解决实际的问题。 1.模型规模…

计网 - 域名解析的工作流程

文章目录 Pre引言1. DNS是什么2. 域名结构3. 域名解析的工作流程4. 常见的DNS记录类型5. DNS安全6. 未来的发展趋势 Pre 计网 - DNS 域名解析系统 引言 在我们日常使用互联网时&#xff0c;经常会输入各种域名来访问网站、发送电子邮件或连接其他网络服务。然而&#xff0c;我…

Java中的关键字

✨✨ 所属专栏&#xff1a; Java基石&#xff1a;深入探索Java核心基础✨✨ &#x1f388;&#x1f388;作者主页&#xff1a; 喔的嘛呀&#x1f388;&#x1f388; Java中的关键字是一些具有特殊含义的单词&#xff0c;它们在语法中有特定的用途&#xff0c;不能用作标识符&am…

[力扣 Hot100]Day32 随机链表的复制

题目描述 给你一个长度为 n 的链表&#xff0c;每个节点包含一个额外增加的随机指针 random &#xff0c;该指针可以指向链表中的任何节点或空节点。 构造这个链表的 深拷贝。 深拷贝应该正好由 n 个 全新节点组成&#xff0c;其中每个新节点的值都设为其对应的原节点的值。新…