nio 读取目录所有文件

在先前的文章中,我讨论了文件和目录的创建( 创建文件和目录 )以及选择( 列出和过滤目录内容 )。 采取的最后一个合乎逻辑的步骤是探索我们如何使用它们以及如何使用它们。 这是库的一部分,已进行了很大的重新设计。 这方面的更新包括保证某些操作的原子性,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

nio 读取目录所有文件

nio 读取目录所有文件_在NIO.2中使用文件和目录相关推荐

  1. java 检测目录下的文件_如何在Java中检查文件是目录还是文件

    java 检测目录下的文件 java.io.File class contains two methods using which we can find out if the file is a d ...

  2. java 删除压缩zip文件_从ZIP存档中删除文件,而无需在Java或Python中解压缩 - java...

    从ZIP存档中删除文件,而无需使用Java(首选)或Python解压缩 你好 我使用包含数百个高度压缩的文本文件的大型ZIP文件.解压缩ZIP文件时,可能要花一些时间,并且很容易消耗多达20 GB的磁 ...

  3. tomcat temp 大量 upload 文件_问题:JavaWeb中实现文件上传的方式有哪些?

    问题:JavaWeb中实现文件上传的方式有哪些? 上回我们说了下文件下载的方式有哪些,这次我们从不同的环境下简单来说说文件上传的方式有哪些. 文件上传的方式 Servlet2.5 方式 Servlet ...

  4. kotlin读取sd卡里的文件_如何在Kotlin中写入文件?

    其他有趣的变化,因此您可以看到Kotlin的强大功能: 通过创建字符串以一次全部写入的快速版本: File("somefile.txt").writeText(history.en ...

  5. 如何用python创建文件_如何在python中编辑文件并创建一个新的文件?

    我有一个很大的文本文件(分隔的),就像下面这个小例子:>ENST00000511961.1|ENSG00000013561.13|OTTHUMG00000129660.5|OTTHUMT0000 ...

  6. java 创建文件夹的方法_java中创建文件夹的方法

    java中创建文件夹的方法 发布时间:2020-06-10 11:46:49 来源:亿速云 阅读:461 作者:Leah 这篇文章给大家分享的是java中创建文件夹的方法.小编觉得挺实用的,因此分享给 ...

  7. mfc检测一个目录是否产生新文件_细数Java8中那些让人纵享丝滑的文件操作

    在丑陋的 Java I/O 编程方式诞生多年以后,Java终于简化了文件读写的基本操作. 打开并读取文件对于大多数编程语言来是非常常用的,由于 I/O 糟糕的设计以至于很少有人能够在不依赖其他参考代码 ...

  8. python多线程读取文件夹下的文件_是否可以使用python多线程从文件夹数读取文件数,并处理这些文件以获得组合结果?...

    我认为学习使用线程的最简单方法是在concurrent.futures模块中使用ThreadPoolExecutor类,因为它比通常的同步for循环多了几行.尤其是在Python3中,但这可以适用于P ...

  9. python查看目录是否存在_如何检查Python中是否存在文件或目录

    编写Python脚本时,仅当文件或目录不存在时,才可能要执行某些操作.例如,您可能想读取数据或将数据写入配置文件,或者仅在不存在的情况下才创建文件. 在Python中,有多种方法可以检查文件是否存在并 ...

最新文章

  1. CSS 框模型——规定了元素框处理元素内容、内边距、边框和外边距的方式
  2. OpenCv 如何对图像的像素进行操作
  3. SAP Fiori Elements - how is read only field implemented in UI
  4. 【贪心】最大连续数列的和
  5. 64位游戏找call_网络小游戏怎么修改技能满级,满血?教大家一个很简单的修改方法!...
  6. Pytorch中 .numpy() .item() .cpu() 区别
  7. pandas.describe()参数的意义
  8. python周期执行-用Python执行周期性动作
  9. dom元素滚动条高度 js_javascript 设置元素滚动大小
  10. 基于php+MySQL电脑外设商城网站 毕业设计-附源码271538
  11. PDF是什么格式?如何编辑PDF文件?
  12. 轻松获奖五一数学建模和蓝桥杯
  13. 计算思维是利用计算机,计算机思维论文
  14. hdu3966 树链剖分+线段树 裸题
  15. 查找农历生日与阳历生日属于同一天的次数和年份
  16. 传奇类手游是怎么做推广的?
  17. 【以太网硬件十七】什么!?网线边传数据还能边供电?
  18. java poi 将公文套红 并 电子签章
  19. 2018-9-3-vue的tabs表单代码的思考
  20. # c语言版:实例:输入一个时间值s,它是距离当日午夜的秒值,计算目前的时间,时间按00:00:00格式输出

热门文章

  1. 【结论】Number(jzoj(gz) 1781)
  2. Spark入门(十)之Distinct去重
  3. Oracle入门(十四E)之条件表达式case和deocde函数
  4. Java Map集合面试题汇总
  5. java的for循环
  6. 04-插入操作更新操作删除操作
  7. 【JDBC】Eclipse连接Mysql
  8. publiccms实现遍历多级分类下的不同样式内容
  9. 被黑客盯上了…数据都给打包带走了…
  10. 代码调用NullPointerException(NPE)