简介

目录和文件傻傻分不清楚,目录和文件的本质到底是什么?在java中怎么操纵目录,怎么遍历目录。本文F师兄会为大家一一讲述。

linux中的文件和目录

小师妹:F师兄,我最近有一个疑惑,java代码中好像只有文件没有目录呀,是不是当初发明java的大神,一不小心走了神?

F师兄:小师妹真勇气可嘉呀,敢于质疑权威是从小工到专家的最重要的一步。想想F师兄我,从小没人提点,老师讲什么我就信什么,专家说什么我就听什么:股市必上一万点,房子是给人住的不是给人炒的,原油宝当然是小白理财必备产品....然后,就没有然后了。

更多精彩内容且看:

更多内容请访问www.flydean.com

虽然java中没有目录的概念只有File文件,而File其实是可以表示目录的:

public boolean isDirectory()

File中有个isDirectory方法,可以判断该File是否是目录。

File和目录傻傻分不清楚,小师妹,有没有联想到点什么?

小师妹:F师兄,我记得你上次讲到Linux下面所有的资源都可以看做是文件,在linux下面文件和目录的本质是不是一样的?

对的,在linux下面文件是一等公民,所有的资源都是以文件的形式来区分的。

什么扇区,逻辑块,页之类的底层结构我们就不讲了。我们先考虑一下一个文件到底应该包含哪些内容。除了文件本身的数据之外,还有很多元数据的东西,比如文件权限,所有者,group,创建时间等信息。

在linux系统中,这两个部分是分开存储的。存放数据本身的叫做block,存放元数据的叫做inode。

inode中存储了block的地址,可以通过inode找到文件实际数据存储的block地址,从而进行文件访问。考虑一下大文件可能占用很多个block,所以一个inode中可以存储多个block的地址,而一个文件通常来说使用一个inode就够了。

为了显示层级关系和方便文件的管理,目录的数据文件中存放的是该目录下的文件和文件的inode地址,从而形成了一种一环套一环,圆环套圆环的链式关系。

上图列出了一个通过目录查找其下文件的环中环布局。

我想java中目录没有单独列出来一个类的原因可能是参考了linux底层的文件布局吧。

目录的基本操作

因为在java中目录和文件是公用File这个类的,所以File的基本操作目录它全都会。

基本上,目录和文件相比要多注意下面三类方法:

public boolean isDirectory()
public File[] listFiles()
public boolean mkdir()

为什么说是三类呢?因为还有几个和他们比较接近的方法,这里就不一一列举了。

isDirectory判断该文件是不是目录。listFiles列出该目录下面的所有文件。mkdir创建一个文件目录。

小师妹:F师兄,之前我们还以目录的遍历要耗费比较长的时间,经过你一讲解目录的数据结构,感觉listFiles并不是一个耗时操作呀,所有的数据都已经准备好了,直接读取出来就行。

对,看问题不要看表面,要看到隐藏在表面的本质内涵。你看师兄我平时不显山露水,其实是真正的中流砥柱,堪称公司优秀员工模范。

小师妹:F师兄,那平时也没看上头表彰你啥的?哦,我懂了,一定是老板怕表彰了你引起别人的嫉妒,会让你的好好大师兄的形象崩塌吧,看来老板真的懂你呀。

目录的进阶操作

好了小师妹,你懂了就行,下面F师兄给你讲一下目录的进阶操作,比如我们怎么拷贝一个目录呀?

小师妹,拷贝目录简单的F师兄,上次你就教我了:

cp -rf

一个命令的事情不就解决了吗?难道里面还隐藏了点秘密?

咳咳咳,秘密倒是没有,小师妹,我记得你上次说要对java从一而终的,今天师兄给你介绍一个在java中拷贝文件目录的方法。

其实Files工具类里已经为我们提供了一个拷贝文件的优秀方法:

public static Path copy(Path source, Path target, CopyOption... options)

使用这个方法,我们就可以进行文件的拷贝了。

如果想要拷贝目录,就遍历目录中的文件,循环调用这个copy方法就够了。

小师妹:且慢,F师兄,如果目录下面还有目录的,目录下还套目录的情况该怎么处理?

这就是圈套呀,看我用个递归的方法解决它:

public void useCopyFolder() throws IOException {
File sourceFolder = new File("src/main/resources/flydean-source");
File destinationFolder = new File("src/main/resources/flydean-dest");
copyFolder(sourceFolder, destinationFolder);
} private static void copyFolder(File sourceFolder, File destinationFolder) throws IOException
{
//如果是dir则递归遍历创建dir,如果是文件则直接拷贝
if (sourceFolder.isDirectory())
{
//查看目标dir是否存在
if (!destinationFolder.exists())
{
destinationFolder.mkdir();
log.info("目标dir已经创建: {}",destinationFolder);
}
for (String file : sourceFolder.list())
{
File srcFile = new File(sourceFolder, file);
File destFile = new File(destinationFolder, file);
copyFolder(srcFile, destFile);
}
}
else
{
//使用Files.copy来拷贝具体的文件
Files.copy(sourceFolder.toPath(), destinationFolder.toPath(), StandardCopyOption.REPLACE_EXISTING);
log.info("拷贝目标文件: {}",destinationFolder);
}
}

基本思想就是遇到目录我就遍历,遇到文件我就拷贝。

目录的腰疼操作

小师妹:F师兄,假如我想删除一个目录中的文件,或者我们想统计一下这个目录下面到底有多少个文件该怎么做呢?

虽然这些操作有点腰疼,还是可以解决的,Files工具类中有个方法叫做walk,返回一个Stream对象,我们可以使用Stream的API来对文件进行处理。

删除文件:

public void useFileWalkToDelete() throws IOException {
Path dir = Paths.get("src/main/resources/flydean");
Files.walk(dir)
.sorted(Comparator.reverseOrder())
.map(Path::toFile)
.forEach(File::delete);
}

统计文件:

 public void useFileWalkToSumSize() throws IOException {

        Path folder = Paths.get("src/test/resources");
long size = Files.walk(folder)
.filter(p -> p.toFile().isFile())
.mapToLong(p -> p.toFile().length())
.sum();
log.info("dir size is: {}",size);
}

总结

本文介绍了目录的一些非常常见和有用的操作。

本文的例子https://github.com/ddean2009/learn-java-io-nio

本文作者:flydean程序那些事

本文链接:http://www.flydean.com/java-io-directory/

本文来源:flydean的博客

欢迎关注我的公众号:程序那些事,更多精彩等着您!

小师妹学JavaIO之:目录还是文件的更多相关文章

  1. 小师妹学JavaIO之:文件系统和WatchService

    目录 简介 监控的痛点 WatchService和文件系统 WatchSerice的使用和实现本质 总结 简介 小师妹这次遇到了监控文件变化的问题,F师兄给小师妹介绍了JDK7 nio中引入的Watc ...

  2. 小师妹学JavaIO之:文件File和路径Path

    简介 文件和路径有什么关系?文件和路径又隐藏了什么秘密?在文件系统的管理下,创建路径的方式又有哪些?今天F师兄带小师妹再给大家来一场精彩的表演. 文件和路径 小师妹:F师兄我有一个问题,java中的文 ...

  3. 小师妹学JavaIO之:MappedByteBuffer多大的文件我都装得下

    目录 简介 虚拟地址空间 详解MappedByteBuffer MapMode MappedByteBuffer的最大值 MappedByteBuffer的使用 MappedByteBuffer要注意 ...

  4. 小师妹学JavaIO之:用Selector来发好人卡

    目录 简介 Selector介绍 创建Selector 注册Selector到Channel中 SelectionKey selector 和 SelectionKey 总的例子 总结 简介 NIO有 ...

  5. 小师妹学JavaIO之:NIO中Channel的妙用

    目录 简介 Channel的分类 FileChannel Selector和Channel DatagramChannel SocketChannel ServerSocketChannel Asyn ...

  6. 小师妹学JavaIO之:Buffer和Buff

    目录 简介 Buffer是什么 Buffer进阶 创建Buffer Direct VS non-Direct Buffer的日常操作 向Buffer写数据 从Buffer读数据 rewind Buff ...

  7. 小师妹学JavaIO之:NIO中那些奇怪的Buffer

    目录 简介 Buffer的分类 Big Endian 和 Little Endian aligned内存对齐 总结 简介 妖魔鬼怪快快显形,今天F师兄帮助小师妹来斩妖除魔啦,什么BufferB,Buf ...

  8. 小师妹学IO系列文章集合-附PDF下载

    目录 第一章 IO的本质 IO的本质 DMA和虚拟地址空间 IO的分类 IO和NIO的区别 总结 第二章 try with和它的底层原理 简介 IO关闭的问题 使用try with resource ...

  9. 小师妹学JVM之:JVM的架构和执行过程

    目录 简介 JVM是一种标准 java程序的执行顺序 JVM的架构 类加载系统 运行时数据区域 执行引擎 总结 简介 JVM也叫Java Virtual Machine,它是java程序运行的基础,负 ...

随机推荐

  1. PMS学习

    一,PMS的adb相关重要指令 1,adb shell dumpsys package(dump所有的系统内apk信息) 2,adb shell dumpsys package “com.androi ...

  2. Vue中如何监听组件的原生事件

    在首页开发中,右下角有一个返回顶部的小箭头,将它单独封装成一个BackTop组件,但是它何时出现需要依赖于首页的滑动,即另外一个Scroll组件.如果直接在BackTop组件里面监听,则需要通过thi ...

  3. 初识Page Object

    PageObject是UI自动化测试项目开发实践的最佳设计模式之一,它的主要特点体现在对界面交互细节的封装上,使测试用例更加专注于业务的操作,从而提高测试用例的可维护性. 1.认识Page Objec ...

  4. Spring + Struts + Hibernate + Bootstrap-table 实现分页和增删改查

    1.bootstrap界面效果图: 2.Teacher实体类 public class Teacher { private int id; private String name; private S ...

  5. eclipse Maven操作出现No compiler is provided in this environment.Perhaps you are running on a JRE rather than a JDK?

    右键 pom.xml -> Run as -> Maven install 后出现类似如下错误: 解决方法: 1)选择项目后,点击 eclipse 导航栏中 [Window]-->[ ...

  6. docker的镜像加速

    docker加速配置 1,阿里云镜像加速 1.登录:https://dev.aliyun.com/search.html 2.登录阿里云 搜索   容器镜像服务  找到后如下图 ‘ 您可以通过修改da ...

  7. JavaScript实现树深度优先和广度优先遍历搜索

    1.前置条件 我们提前构建一棵树,类型为 Tree ,其节点类型为 Note.这里我们不进行过多的实现,简单描述下 Note 的结构: class Node{ constructor(data){ t ...

  8. Python学习之路【第一篇】:Python简介与入门

    Python简介 一.什么是Python Python 是一个高层次的结合了解释性.编译性.互动性和面向对象的脚本语言. Python 的设计具有很强的可读性,相比其他语言经常使用英文关键字,其他语言 ...

  9. MP4视频流base64数据转成Blob对象

    网上一大堆对图片base64转Blob.File的方法 很少有视频mp4转的,可能是因为原理相同的原因吧!但在项目中针对视频流base64转Blob对象时,花了好长时间才成功,特专门记录一下! APP ...

  10. php序列化和反序列化学习

    1.什么是序列化 序列化说通俗点就是把一个对象变成可以传输的字符串. 1.举个例子,不知道大家知不知道json格式,这就是一种序列化,有可能就是通过array序列化而来的.而反序列化就是把那串可以传输 ...