在NIO.2中使用文件和目录

在先前的文章中,我讨论了文件和目录的创建( 创建文件和目录 )以及选择( 列出和过滤目录内容 )。 采取的最后一个合乎逻辑的步骤是探索我们如何使用它们以及如何使用它们。 这是库的一部分,它经过了重新设计。 这方面的更新包括保证某些操作的原子性,API改进,性能优化以及引入适当的异常层次结构,这些层次结构取代了IO库以前版本中的boolean返回方法。

开启档案

在开始阅读和写入文件之前,我们需要介绍这些操作的一个共同基础-文件的打开方式。 文件的打开方式直接影响这些操作的结果及其性能。 让我们看一下打开枚举java.nio.file.StandardOpenOption包含的文件的标准选项:

标准打开选项
描述
APPEND 如果打开该文件以进行WRITE访问,则字节将被写入文件的末尾而不是开头。
CREATE 如果不存在,请创建一个新文件。
CREATE_NEW 创建一个新文件,如果文件已经存在则失败。
DELETE_ON_CLOSE 关闭删除。
DSYNC 要求对文件内容的每次更新都同步写入基础存储设备。
READ 打开以进行读取访问。
SPARSE 稀疏文件。
SYNC 要求对文件内容或元数据的每次更新都同步写入基础存储设备。
TRUNCATE_EXISTING 如果该文件已经存在并且已打开以进行WRITE访问,则其长度将被截断为0。
WRITE 打开以进行写访问。

这些都是开发人员您可能需要正确处理文件打开(无论是读取还是写入)的所有标准选项。

读取文件

在读取文件时,NIO.2提供了几种方法来实现–每种方法都有其优缺点。 这些方法如下:

  • 将文件读入字节数组
  • 使用无缓冲流
  • 使用缓冲流

让我们来看看第一个选项。 类Files提供了方法readAllBytes来做到这一点。 将文件读入字节数组似乎很简单,但这可能仅适用于非常有限的文件范围。 由于我们将整个文件放入内存中,因此必须注意该文件的大小。 仅当我们尝试读取小文件时,使用此方法才是合理的,并且可以立即完成。 如以下代码段所示,这是非常简单的操作:

Path filePath = Paths.get("C:", "a.txt");if (Files.exists(filePath)) {try {byte[] bytes = Files.readAllBytes(filePath);String text = new String(bytes, StandardCharsets.UTF_8);System.out.println(text);} catch (IOException e) {throw new RuntimeException(e);}
}

上面的代码首先将文件读取到字节数组中,然后使用以下输出构造包含该文件内容的字符串对象:

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam sit amet justo nec leo euismod porttitor. Vestibulum id sagittis nulla, eu posuere sem. Cras commodo, massa sed semper elementum, ligula orci malesuada tortor, sed iaculis ligula ligula et ipsum.

当我们需要以字符串形式读取文件的内容时,可以使用上面的代码。 但是,这种解决方案不是很干净,我们可以使用类Files readAllLines来避免这种尴尬的构造。 当需要逐行读取人类可读的输出时,此方法可作为读取文件的便捷解决方案。 此方法的使用再次非常简单,并且与前面的示例非常相似(有相同的限制):

Path filePath = Paths.get("C:", "b.txt");if (Files.exists(filePath)) {try {List<String> lines = Files.readAllLines(filePath, StandardCharsets.UTF_8);for (String line : lines) {System.out.println(line);}} catch (IOException e) {throw new RuntimeException(e);}
}

具有以下输出:

Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Aliquam sit amet justo nec leo euismod porttitor.
Vestibulum id sagittis nulla, eu posuere sem.
Cras commodo, massa sed semper elementum, ligula orci malesuada tortor, sed iaculis ligula ligula et ipsum.

使用流读取文件

继续使用更复杂的方法,我们总是可以使用良好的旧流,就像我们以前使用该库的以前版本一样。 既然这是众所周知的基础,我将仅展示如何获取这些流的实例。 首先,我们可以通过调用newInputStream方法从类Files检索InputStream实例。 像往常一样,可以进一步使用装饰器模式,并从中输出缓冲流。 为了方便起见,使用方法newBufferedReader 。 这两个方法都返回一个流实例,该实例是普通的旧java.io对象。

Path filePath1 = Paths.get("C:", "a.txt");
Path filePath2 = Paths.get("C:", "b.txt");InputStream is = Files.newInputStream(filePath1);
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);BufferedReader reader = Files.newBufferedReader(filePath2, StandardCharsets.UTF_8);

写入文件

写入文件与NIO.2库提供的一系列工具中的读取过程相似,因此只需回顾一下:

  • 将字节数组写入文件
  • 使用无缓冲流
  • 使用缓冲流

再次让我们首先探索字节数组选项。 毫不奇怪,类Files支持我们方法write两个变体。 我们正在从数组或文本行中写入字节,我们在这里需要关注StandardOpenOptions ,因为这两种方法都可能受到这些修饰符的自定义选择的影响。 默认情况下,如果没有将StandardOpenOption传递给该方法,则write方法的行为就像存在CREATETRUNCATE_EXISTINGWRITE选项一样(如Javadoc中所述)。 话虽如此,请注意不要使用默认(无打开选项)版本的write方法,因为它要么创建一个新文件,要么最初将现有文件截断为零大小。 写入完成后,文件会自动关闭-成功写入后会引发异常。 对于文件大小,适用与readAllBytes相同的限制。

下面的示例演示如何将字节数组写入文件。 请注意,由于write方法的默认行为,因此没有任何检查方法。 该示例可以多次运行,并具有两个不同的结果。 第一次运行将创建一个文件,将其打开以进行写入,然后将数组bytes写入此文件。 此代码的任何后续调用都将擦除该文件,并将bytes数组的内容写入此空文件。 两次运行都将导致文本为“ Hello world!”的封闭文件。 写在第一行。

Path newFilePath = Paths.get("/home/jstas/a.txt");
byte[] bytes = new byte[] {0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x21};try {Files.write(newFilePath, bytes);
} catch(IOException e) {throw new RuntimeException(e);
}

当我们需要写行而不是字节时,我们可以将字符串转换为字节数组,但是,还有一种更方便的方法。 只需准备一行列表,然后将其传递给write方法即可。 请注意以下示例中两个StandardOpenOption的使用。 通过使用这些选项,我可以确保存在一个文件(如果不存在,则会创建该文件)以及将数据追加到该文件的方式(因此不会丢失任何先前写入的数据)。 整个例子很简单,看一下:

Path filePath = Paths.get("/home/jstas/b.txt");List<String> lines = new ArrayList<>();
lines.add("Lorem ipsum dolor sit amet, consectetur adipiscing elit.");
lines.add("Aliquam sit amet justo nec leo euismod porttitor.");
lines.add("Vestibulum id sagittis nulla, eu posuere sem.");
lines.add("Cras commodo, massa sed semper elementum, ligula orci malesuada tortor, sed iaculis ligula ligula et ipsum.");try {Files.write(filePath, lines, StandardCharsets.UTF_8, StandardOpenOption.CREATE, StandardOpenOption.APPEND);
} catch (IOException e) {throw new RuntimeException(e);
}

使用流写入文件

对于较大的文件,使用字节数组可能不是一个好主意。 这是流进入的时间。类似于阅读本章,我将不解释流或如何使用它们。 我宁愿专注于一种检索其实例的方法。 类Files提供了newOutputStream方法,该方法接受StandardOpenOption来自定义流行为。 默认情况下,当没有将StandardOpenOption传递给该方法时,流write方法的行为就像存在CREATETRUNCATE_EXISTINGWRITE选项一样(如Javadoc中所述)。 该流没有被缓冲,但是通过一点装饰器魔术,您可以创建BufferedWriter实例。 为了解决这种不便,NIO.2附带了newBufferWriter方法,该方法可立即创建缓冲的流实例。 以下代码段显示了两种方式:

Path filePath1 = Paths.get("/home/jstas/c.txt");
Path filePath2 = Paths.get("/home/jstas/d.txt");OutputStream os = Files.newOutputStream(filePath1);
OutputStreamWriter osw = new OutputStreamWriter(os);
BufferedWriter bw = new BufferedWriter(osw);BufferedWriter writer = Files.newBufferedWriter(filePath2, StandardCharsets.UTF_8, StandardOpenOption.CREATE, StandardOpenOption.APPEND);

复制和移动文件和目录

复制文件和目录

NIO.2最受欢迎的功能之一是处理复制和移动文件和目录的更新方式。 为了使所有内容保持一致,设计人员决定在新文件系统API中引入两个父(标记)接口: OpenOptionCopyOption (这两个接口均来自包java.nio.file )。 上一章提到的StandardOpenOption枚举实现了OpenOption接口。 CopyOption接口具有两个实现,其中一个已经在关于NIO.2中的Links的帖子中见过。 你们中有些人可能还记得LinkOption枚举,它被称为实现指导方法来处理链接相关的操作。 但是,还有另一种实现–包java.nio.file StandardCopyOption枚举。 再次,我们将看到另一个枚举–用于指导复制操作。 因此,在深入研究任何代码之前,让我们回顾一下使用不同的复制选项可以实现的目标。

标准复印选项
描述
ATOMIC_MOVE 将文件作为原子文件系统操作移动。
COPY_ATTRIBUTES 将属性复制到新文件。
REPLACE_EXISTING 替换现有文件(如果存在)。


使用这些选项来指导您的IO操作非常简单,也很简单。 由于我们正在尝试复制文件,因此ATOMIC_MOVE使用意义不大(您仍然可以使用它,但最终会出现java.lang.UnsupportedOperationException: Unsupported copy option )。 类Files提供了三种copy方法,可用于不同目的:

  • copy(InputStream in, Path target, CopyOption... options)
    • 将所有字节从输入流复制到文件。
  • copy(Path source, OutputStream out)
    • 将所有字节从文件复制到输出流。
  • copy(Path source, Path target, CopyOption... options)
    • 将文件复制到目标文件。

在我们获得任何代码之前,我相信最好了解copy方法的最重要的行为功能(上述三个方法中的最后一个)。 copy方法的行为如下(基于Javadoc):

  • 默认情况下,如果目标文件已经存在或为符号链接,则复制失败。
  • 如果源和目标是同一文件,则该方法将完成而无需复制该文件。 (有关更多信息,请查看类Files方法isSameFile
  • 不需要将文件属性复制到目标文件。
  • 如果源文件是目录,则它将在目标位置创建一个空目录(不复制目录中的条目)。
  • 复制文件不是原子操作。
  • 自定义实现可能会带来新的特定选项。

这些是copy方法内部工作的核心原理。 现在是查看代码示例的好时机。 由于此方法非常易于使用,因此可以将其实际使用(使用最常见的copy方法形式)。 如预期的那样,以下代码将复制源文件(并可能覆盖目标文件)并保留文件属性:

Path source = Paths.get("/home/jstas/a.txt");
Path target = Paths.get("/home/jstas/A/a.txt");try {Files.copy(source, target, StandardCopyOption.COPY_ATTRIBUTES, StandardCopyOption.REPLACE_EXISTING);
} catch (IOException e) {throw new RuntimeException(e);
}

这里没有什么大的惊喜–代码复制带有文件属性的源文件。 如果您觉得我忘记了(不是空的)目录,请让我向我保证。 也可以使用NIO.2复制,移动或删除填充的目录,但这是我将在下一篇文章中介绍的内容,因此您将不得不等待几天。

移动文件和目录

在移动文件时,我们再次需要能够指定选项,以指导方法从Filesmove的过程。 在这里,我们利用了上一章中提到的StandardCopyOptions 。 两个相关选项是ATOMIC_MOVEREPLACE_EXISTING 。 首先,让我们从一些基本特征入手,然后继续进行代码示例:

  • 默认情况下,如果目标文件已存在,则move方法将失败。
  • 如果源文件和目标文件是同一文件,则该方法将完成而不移动文件。 (有关更多信息,请查看类Files方法isSameFile
  • 如果源是符号链接,则链接本身将被移动。
  • 如果源文件是目录,则必须为空才能移动。
  • 不需要移动文件属性。
  • 可以将移动文件配置为原子操作,但不必这样做。
  • 自定义实现可能会带来新的特定选项。

代码非常简单,因此让我们看下面的代码片段:

Path source = Paths.get("/home/jstas/b.txt");
Path target = Paths.get("/home/jstas/A/b.txt");try {Files.move(source, target, StandardCopyOption.ATOMIC_MOVE, StandardCopyOption.REPLACE_EXISTING);
} catch(IOException e) {throw new RuntimeException(e);
}

如预期的那样,代码以原子操作移动源文件。

删除文件和目录

本文的最后一部分致力于删除文件和目录。 再次删除文件非常简单,可以使用两种可能的方法来调用(通常都从Files类):

  • public static void delete(Path path)
  • public static boolean deleteIfExists(Path path)

两种方法使用相同的规则:

  • 默认情况下,当文件是目录并且不为空时,删除方法将失败,并出现DirectoryNotEmptyException
  • 如果文件是符号链接,则链接本身将被删除。
  • 删除文件可能不是原子操作。
  • 如果文件已打开或被JVM或其他软件使用,则可能不会删除文件。
  • 自定义实现可能会带来新的特定选项。
Path newFile = Paths.get("/home/jstas/c.txt");
Path nonExistingFile = Paths.get("/home/jstas/d.txt");try {Files.createFile(newFile);Files.delete(newFile);System.out.println("Any file deleted: " + Files.deleteIfExists(nonExistingFile));
} catch(IOException e) {throw new RuntimeException(e);
}

输出:

Any file deleted: false

翻译自: https://www.javacodegeeks.com/2014/06/working-with-files-and-directories-in-nio-2.html

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

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

相关文章

工作流的设计,业务流程图的绘制与编辑,工作流软件,工作流源代码组件库,开发平台,开发引擎...

基于业务流程的工作流系统在当前的软件工业中占据着非常重要的部分&#xff0c;开发此类系统, 最困难的部分就是业务流程建模和电子表单的可视化界面部分,这部分界面要求有快速的响应时间, 完善的逻辑关系,以及根据需求不断变化而必须具备的灵活编辑功能. E-Form可视化图形源码…

upload file more than 4MB

http://www.websupergoo.com/abcupload.net-1.htm 转载于:https://www.cnblogs.com/stevengeng/archive/2004/12/30/84274.html

Ajax全接触(1)

Ajax全称&#xff1a;Asynchronous JavaScript and XML(异步的JavaScript和XML) .Ajax不是某种编程语言 是一种在无需重新加载整个网页的情况之下能够更新部分网页的技术。 后面引入XMLHttpRequest对象用于后台和服务器交换数据&#xff0c;可以在不重新加载整个页面的前提下…

关于hibernate字段映射@colunm出现的问题以及jpa驼峰大写转_小写的问题探究

关于hibernate字段映射colunm出现的问题以及jpa驼峰大写转_小写的问题探究2018年04月24日 15:47:26 守望dfdfdf 阅读数&#xff1a;735 标签&#xff1a; colunmhibernate表映射实体类 更多个人分类&#xff1a; 工作 问题编辑版权声明&#xff1a;本文为博主原创文章&#xff…

窗口模版

窗口模版 1. 定义窗口模版的ID 在wgui_categories_defs.h文件中有枚举enum MMI_CATEGORY_ID_LIST 首先要在MMI_CATEGORY_ID_LIST中添加窗口模版的ID&#xff0c;例如&#xff1a; MMI_CATEGORY36_ID 2. 控件坐标和控件数组的定义 CustCoordinates.c (plutommi"…

玩Java 8 – Lambda,路径和文件

我最近需要读取一堆文件&#xff0c;而不是仅仅抓住我和可能是大多数开发人员拥有的旧FileUtils.java&#xff0c;然后从一个项目复制到另一个项目&#xff0c;我决定快速了解其他方法。 是的&#xff0c;我知道有Commons IO和Google IO &#xff0c;我为什么还要打扰&#xf…

vs.net2003无法打开.NET的Web应用服务

今天想打开web项目时提示&#xff1a;Visual Studio .NET 已检测到指定的Web服务器运行的不是ASP.NET 1.1版。您将无法运行ASP.NET Web应用原因大概是自己原来安装VS.NET2003时没有安装IIS&#xff0c;后来才装上的。自己重新安装了.NET Framework1.1还是不行。后来找到了找这个…

vue组件-使用插槽分发内容(slot)

slot--使用插槽分发内容&#xff08;位置、槽口&#xff1b;作用: 占个位置&#xff09; 官网API&#xff1a; https://cn.vuejs.org/v2/guide/components.html#使用插槽分发内容 使用组件时&#xff0c;有时子组件不知道会收到什么内容&#xff0c;这是由父组件决定的。 一…

LeetCode 上最难的链表算法题,没有之一!

题目来源于 LeetCode 第 23 号问题&#xff1a;合并 K 个排序链表。 该题在 LeetCode 官网上有关于链表的问题中标注为最难的一道题目&#xff1a;难度为 Hard &#xff0c;通过率在链表 Hard 级别目前最低。 题目描述 合并 k 个排序链表&#xff0c;返回合并后的排序链表。请分…

处理Akka应用程序中的每个事件

这里的事件&#xff0c;那里的事件&#xff0c;到处都是事件。 发布有关检查每一项Akka事件最终都能找到归宿的信息。 Akka和基于事件的反应式应用程序是创建软件的新方法。 在当前基于Scala的项目中&#xff0c;我们非常密集地使用Akka。 事件非常适合我们的用例&#xff0c;…

js设置select列表中特定项为选中状态

设置select中text"paraText"的第一个Item为选中 function jsSelectItemByValue(objSelect,objItemText) { //判断是否存在 var isExit false; for(var i0;i<objSelect.options.length;i) { if(objSelect.options[i].text objItemText) { objSelect.options[i].s…

vue 导出html

vue的html代码 <template> <div class"contentsss" ref"test"> <button click"export2Excel">导出</button> </div> </template>methods方法 export2Excel() { var a document.createElement("a"…

js快排

快排的思路&#xff1a;选定一个基准数&#xff0c;要使得基数的左边的数字全部小于它&#xff0c;右边的数字全部大于它。分别设i和j从左右开始寻找&#xff0c;从左边找到第一个比基数大的数&#xff0c;从右边找到第一个比基数小的数&#xff0c;然后交换这两个数。 当i和j…

jzoj 6302. 提高组

Description 详见OJ Solution 对于\(limit1,2\)就是使序列\(1~n\)的排列。 对于\(limit3\)&#xff0c;我们可以将其看做是两个最长上升子序列正好覆盖整个序列&#xff0c;证明显然。 我们可以做一个前缀\(max\)序列。这样对于\(max[i]\)&#xff0c;保证\(max[i]>i\)。 而…

使用IntelliJ ..达2周,到目前为止一切正常

几乎已经过去了2个星期&#xff0c;我已经完全切换到IntelliJ作为我在家里和工作中的主要Java IDE。 到目前为止一切顺利&#xff0c;这是我的初步发现。 迁移 &#xff1a;我花了几个小时来迁移项目。 最终&#xff0c;如果您的项目已经Mavenized&#xff0c;事情就简单了&am…

WEB框架研究笔记一(准备)

DELPHI框架基本完成之后&#xff0c;开发一个WEB框架的想法越来越强烈&#xff0c;一直以来没有过完整的开发过一个WEB项目&#xff0c;这几年来&#xff0c;也就看过几个WEB的产品&#xff0c;了解了一下Struts&#xff0c;去年研究了一下DORADO&#xff0c;顺便了解了SpringH…

备份文件夹

用到的API和数据结构&#xff1a; WINDOWS数据结构&#xff1a; WIN32_FIND_DATA WINDOWS API&#xff1a; FindFirstFile FindNextFile CompareFileTime CopyFIle DeleteFile View Code #include <windows.h> #include <iostream> #include <string> using…

面试整理(1):原生ajax

接到电话面试&#xff0c;有一些送分题答的不好&#xff0c;在这里整理一下 问题&#xff1a;原生ajax的工作流程是怎么样的&#xff1f; 老用封装好的工具&#xff0c;原生的ajax其实并不熟悉&#xff0c;今天复习一下。主要参考http://www.w3school.com.cn/ajax/ 要发一个…

QT

Qt软件 Qt是一个跨平台的C图形用户界面应用程序框架。它提供给应用程序开发者建立艺术级的图形用户界面所需的所用功能。Qt是完全面向对象的&#xff0c;很容易扩展&#xff0c;并且允许真正地组件编程。 自从1996年早些时候&#xff0c;Qt进入商业领域&#xff0c;它已经成为全…

IOS获取资源路径

1. 获取已经添加到xcode工程中的某一资源文件 file.txt 的路径 NSString *filePath_ [[NSBundle mainBundle] pathForResource:"file" ofType:"txt"]; std::string filePath std::string([filePath_ UTF8String]); 2. 对当前xcode工程开通沙盒权限后&#…