自从java 7以来,引入了FIles类和Path接口。他们两封装了用户对文件的所有可能的操作,相比于java 1的File类来说,使用起来方便很多。但是其实一些本质的操作还是很类似的。主要需要知道的是,Path表示路径可以使文件的路径也可以是目录的路径,Files中所有成员都是静态方法,通过路径实现了对文件的基本操作。下面我们首先看看Path接口。

一、Path接口

     和Path接口相关的还有一个类Paths,这个类非常简单,只有两个方法加一个私有构造方法。

public final class Paths {
private Paths() { }
public static Path get(String first, String... more) {
return FileSystems.getDefault().getPath(first, more);
}
public static Path get(URI uri) {/*这个方法我们暂时不研究*/}
}

     大家可以看到,通过Paths的get静态方法,我们可以获得一个Path对象,而实际上我们通常都是通过Paths的这个get方法来获取Path对象。(至于怎么调用这个方法返回的对象,主要是通过调用文件系统的抽象方法来实现的),获得了Path对象,我们就可以调用其内部封装的所有的方法,由于方法比较多,我们一点一点看。

boolean isAbsolute();
Path getFileName();
Path getParent();
int getNameCount();
Path getName(int index);
Path subpath(int beginIndex, int endIndex);
Path resolve(Path other);
Path resolveSibling(Path other);
Path relativize(Path other);
Path toAbsolutePath();
File toFile();

     主要的方法就这么多,其中有些方法的功能乃至具体的实现代码和上篇介绍的File类类似,这里就不在说明了。getFileName这个方法类似于File类的getName方法,返回路径的文件名称(目录名或者文件名),两者实现原理基本一样。

Path p = Paths.get("a","b","c","d","e");
System.out.println(p.getNameCount());
/*执行代码可以看到输出结果:5*/ Path p = Paths.get("a/t","b","c","d","e");
System.out.println(p.getNameCount());
/*执行代码输出结果:6*/

     可以看到,getNameCount方法并不是直接数构建Path对象时传入了几个字符串。当我们调用Path.get方法传入可变字符串作为路径时,它将每个独立的字符串当成一个目录名,使用默认路径分隔符连接这些路径名形成Path路径,而调用getNameCount方法是根据默认路径分隔符的个数来统计返回的。

     getName方法要求传入一个int型索引,在构建路径时,从根路径开始每一层都被编号了,根目录为0,子目录依次加一所以getName方法可以获取任意层次目录的名称。

Path p = Paths.get("a","b","c","d","e");
System.out.println(p.getName(1));
/*输出:b*/

     subpath方法和我们String中的substring类似,给定开始和结束位置的索引值,获取他们之间的路径字符串。

Path p = Paths.get("a","b","c","d","e");
System.out.println(p.subpath(1,3));
/*输出结果:b/c*/

     需要注意一个细节,截取范围[startIndex,endIndex),也就是endIndex位置的值是不会被截取的。

     resolve方法是一个很有意思的方法,按照我的理解,这个方法实现的是对路径的组合的操作。p.resolve(q),如果q是绝对路径,返回结果为q,如果q是相对路径返回结果是p+q,实现了拼接组合。

Path p = Paths.get("a","b","c","d","e");
Path q = Paths.get("c:/users");
System.out.println(p.resolve(q));
/*输出:c:/users*/ Path p = Paths.get("a","b","c","d","e");
Path q = Paths.get("users");
System.out.println(p.resolve(q));
/*输出结果:a\b\c\d\e\users*/

     resolveSibling方法是通过解析当前路径的父目录,产生兄弟路径。

Path p = Paths.get("a","b","c","d","e");
Path q = Paths.get("users");
System.out.println(p.resolveSibling(q));
/*输出结果:a\b\c\d\users*/

     替换了e为users,因为e作为当前目录,而此方法就是在当前目录下生成一个和他同级的兄弟目录。通常可以用来修改当前目录的目录名。(在生成磁盘文件之前)

     接下来说说这个relativize方法,它是一个用来生成一个相对路径的方法。需要额外传入一个Path对象。

Path p = Paths.get("a","b","c","d","e");
Path q = Paths.get("users");
System.out.println(p.relativize(q));
/*输出结果:..\..\..\..\..\users*/ Path p = Paths.get("a","b","c","d","e");
Path q = Paths.get("a","b","c","d","e","f");
System.out.println(p.relativize(q));
/*输出结果:f*/

     通过比较可以发现,所谓生成相对路径,实际上就是,q相对于p。从第二中情况我们可以看出来,整个p可以作为q的父目录,于是相对路径就是当前目录f。对于第一种情况,因为没有找到公共目录,所以整个p作为q的父目录,当然相对于q来说,相对路径就是这样了。

     最后还想啰嗦一句,在Path中有一个方法toFile,这个方法对应于FIle中的toPath,为什么要实现这么两个方法,其实还是为了兼容旧的File类,方便一些旧的系统成功的跨度到新的java标准中来。

二、Files类

     上面说过,整个FIles类中,都是静态方法,没有一个实例域。(足以见得,这个类就是为了实现对文件的各种操作)首先看看对文件的读写操作。

public static InputStream newInputStream(Path path, OpenOption... options)

public static OutputStream newOutputStream(Path path, OpenOption... options)

public static BufferedReader newBufferedReader(Path path, Charset cs)

public static BufferedReader newBufferedReader(Path path)

public static BufferedWriter newBufferedWriter

public static byte[] readAllBytes(Path path)

public static List<String> readAllLines(Path path)

public static Path write(Path path, byte[] bytes, OpenOption... options)

public static long copy(InputStream in, Path target, CopyOption... options)

public static long copy(Path source, OutputStream out)

     方法很多,我们慢慢看,首先有两个方法可以根据Path路径返回InputStream/OutputStream字节流对象,这两个方法为我们下面的一些方法提供了一定的便利,也有两个方法通过Path对象返回BufferedReader/BufferedWriter对象。这些都是对于我们其他的方法是有帮助的。

     readAllBytes内部通过创建InputStream对象来读取所有的字节到给定的字节数组中并返回。readAllLines内部通过创建List数组,使用BufferedReader创建字符缓冲流,一行一行的读取。最后返回List集合。写的操作基本都是读的逆操作,这里不再赘述。

     copy这个方法有多个重载,分别是:

private static long copy(InputStream source, OutputStream sink)

public static long copy(InputStream in, Path target, CopyOption... options)

public static long copy(Path source, OutputStream out)

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

     第一个重载是一个私有的方法,是被被人调用的工具方法。主要的功能是:从一个source流中读取所有的字节并写入sink流中,返回实际读入或写入的字节数。第二个重载是选择将Path对象通过方法newOutputStream,构建了一个OutputStream对象,然后调用第一个重载方法实现copy。完成的功能是:从一个InputStream流中读取所有的字节并写入一个指定的文件中。第三个重载方法主要是:从一个Path文件中读取所有的字节并写入一个OutputStream对象流中。操作流程类似,不在赘述。最后一个重载方法实现的是从一个Path对象复制到另一个Path对象。

//根目录下只有hello.txt文件,没有world文件
Path p = Paths.get("hello.txt");
Path q = Paths.get("world.txt");
Files.copy(p,q);
/*world文件被创建并且hello中的内容被复制到此*/

     对于这个操作,需要注意的几点:如果q在磁盘为位置的文件已经存在将不能完成复制操作,如果p在磁盘位置上没有对应文件此操作依然失败,如果p是一个目录文件,结果会复制一个名为world的目录文件,如果q是一个目录文件则会创建一个无类型的文件(hello中的内容已经被复制进去)。

     说完了有关文件的读写操作,下面说说文件或目录的创建和获取文件的基本信息。

public static Path createFile(Path path, FileAttribute<?>... attrs)

public static Path createDirectory(Path dir, FileAttribute<?>... attrs)

public static Path createDirectories(Path dir, FileAttribute<?>... attrs)

public static Path createTempFile

     因为Path路径中存放的可以是文件类型,也可以是目录类型。那么在创建的时候就需要进行区分了。createFile根据指定路径创建一个指定类型的文件,createDirectory和createDirectories的区别在,如果Path路径上存在着没有被创建的目录,后者会将他们全部都创建。对于创建临时文件,由于用的不多,就不说了。

     对于文件信息的获取主要有以下些方法:

public static boolean isSameFile(Path path, Path path2)
public static boolean isHidden(Path path)
public static String probeContentType(Path path)
public static boolean isDirectory(Path path, LinkOption... options)
public static boolean isRegularFile(Path path, LinkOption... options)
public static long size(Path path)
public static boolean exists(Path path, LinkOption... options)
public static boolean isReadable(Path path)
public static boolean isWritable(Path path)
/*这些方法名字就是注释,相信大家一眼就能识别他们各自的功能*/

     最后谈谈迭代和过滤器,在上篇文章的最后,我们说了FIle的过滤和迭代,因为在File类中,通常都是一次性返回一个File数组或者String数组,这往往是低效的。在Files类中,设计了一个方法newDirectoryStream,返回了一个目录流,可以显著提高效率。

public static DirectoryStream<Path> newDirectoryStream(Path dir)

public static DirectoryStream<Path> newDirectoryStream(Path dir, String glob)

 public static DirectoryStream<Path> newDirectoryStream(Path dir,
DirectoryStream.Filter<? super Path> filter)

     这是三个目录流的重载方法,第一个只需要提供一个Path路径即可,第二个方法提供了一个Path对象和一个glob字符串。glob模式:



第三个方法还外部指定了一个过滤器。具体怎么使用,下面看代码。

DirectoryStream<Path> d = Files.newDirectoryStream(Paths.get("f:/360"));
for (Path p : d){
System.out.println(p.getFileName());
}
//输出结果:
360defender
360sdSetup.exe
360zip
//这是我f盘360文件下的所有文件
DirectoryStream<Path> d = Files.newDirectoryStream(Paths.get("f:/360"),"*.exe");
for (Path p : d){
System.out.println(p.getFileName());
}
//输出结果:
360sdSetup.exe
DirectoryStream<Path> d = Files.newDirectoryStream(Paths.get("f:/360"),new DirectoryStream.Filter<Path>(){
@Override
public boolean accept(Path entry) {
return Files.isDirectory(entry)?true:false;
}
});
for (Path p : d){
System.out.println(p.getFileName());
}
//输出结果:
360defender
360zip

     第三种方法通过显式传入一个过滤器来实现获取子目录中所有的目录。

     如果本文有错误,欢迎大家指出!

java 文件操作(二)---Files和Path的更多相关文章

  1. Java文件操作二:File文件的方法

    一.文件的判断方法 判断方法 .boolean canExecute()判断文件是否可执行 .boolean canRead()判断文件是否可读 .boolean canWrite() 判断文件是否可 ...

  2. Java文件操作源码大全

    Java文件操作源码大全 1.创建文件夹 52.创建文件 53.删除文件 54.删除文件夹 65.删除一个文件下夹所有的文件夹 76.清空文件夹 87.读取文件 88.写入文件 99.写入随机文件 9 ...

  3. 14、Java文件操作stream、File、IO

    1.文件操作涉及到的基本概念 File File类 是文件操作的主要对象中文意义就是 文件 顾名思意 万物皆文件,在计算上看到的所有东西都是文件保存,不管是你的图片.视频.数据库数据等等都是按照基本的 ...

  4. Java 文件操作大全

    Java 文件操作大全 //1.创建文件夹 //import java.io.*; File myFolderPath = new File(str1); try { if (!myFolderPat ...

  5. JAVA文件操作类和文件夹的操作代码示例

    JAVA文件操作类和文件夹的操作代码实例,包括读取文本文件内容, 新建目录,多级目录创建,新建文件,有编码方式的文件创建, 删除文件,删除文件夹,删除指定文件夹下所有文件, 复制单个文件,复制整个文件 ...

  6. java文件操作(普通文件以及配置文件的读写操作)

    转自:java文件操作(普通文件以及配置文件的读写操作) 读取普通文件 : /** * xiangqiao123欢迎你 如果对代码有疑问可以加qq群咨询:151648295 * * 读取MyFile文 ...

  7. Java文件操作API功能与Windows DOS命令和Linux Shell 命令类比

    Java文件操作API功能与Windows DOS命令和Linux Shell 命令类比: Unix/Linux (Bash) Windows(MS-DOS) Java 进入目录 cd cd - 创建 ...

  8. Node.js文件操作二

    前面的博客 Node.js文件操作一中主要是对文件的读写操作,其实还有文件这块还有一些其他操作. 一.验证文件path是否正确(系统是如下定义的) fs.exists = function(path, ...

  9. 【Directory】文件操作(初识文件操作二)

    上篇我们说了关于文件的创建删除更改可以通过File这个类来完成.对于目录的操作其实File类也可以完成创建删除等相关的操作.用法跟文件的方法大致相同. 那么下面就一起来看一下关于目录相关的用法. 一, ...

  10. Java文件操作系列[3]——使用jacob操作word文档

    Java对word文档的操作需要通过第三方组件实现,例如jacob.iText.POI和java2word等.jacob组件的功能最强大,可以操作word,Excel等格式的文件.该组件调用的的是操作 ...

随机推荐

  1. [html5] 学习笔记-html5增强的页面元素

    在 HTML5 中,不仅增加了很多表单中的元素,同时也增加和改良了可以应用在整个页面中的元素.重点包含 figure.figcaption.details.summary.mark.progress. ...

  2. LPC4370使用学习:GPIO的引脚功能使用,和12864OLED模拟I2C驱动

    一: 手中有块LPC4370的开发板,因为便宜,所以引脚引出的不多,而且只有基本的底板资源驱动代码和例程. 看着手册和例程看了老半天,写程序写了半天,结果GPIO老是驱动不起来,因为引脚配置寄存器中有 ...

  3. TCP/IP协议族(二) HTTP报文头解析

    本篇博客我们就来详细的聊一下HTTP协议的常用头部字段,当然我们将其分为请求头和响应头进行阐述.下方是报文头每个字段的格式,首先是头部字段的名称,如Accept,冒号后方紧跟的是该字段名所对应的值,每 ...

  4. Linux驱动技术(五) _设备阻塞/非阻塞读写

    等待队列是内核中实现进程调度的一个十分重要的数据结构,其任务是维护一个链表,链表中每一个节点都是一个PCB(进程控制块),内核会将PCB挂在等待队列中的所有进程都调度为睡眠状态,直到某个唤醒的条件发生 ...

  5. HDU 2186 悼念512汶川大地震遇难同胞——一定要记住我爱你

    悼念512汶川大地震遇难同胞——一定要记住我爱你 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java ...

  6. iOS Foundation框架 -1.常用结构体的用法和输出

    1.安装Xcode工具后会自带开发中常用的框架,存放的地址路径是: /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.plat ...

  7. Python之字符串详解1

    1. 查看类型 name = 'allen' print(type(name)) #查看类型 <class 'str'> #类型为str age = 19 print(type(name) ...

  8. 基于 GCDAsyncSocket,简单实现类似《你猜我画》的 socket 数据传输

    一.前言 Socket Socket 是对 TCP/IP 协议的封装,其中IP协议对应为网络层,TCP 协议对应为传输层,而我们常用的HTTP协议,是位于应用层,在七层模型中HTTP协议是基于 TCP ...

  9. python实现多变量线性回归(Linear Regression with Multiple Variables)

    本文介绍如何使用python实现多变量线性回归,文章参考NG的视频和黄海广博士的笔记 现在对房价模型增加更多的特征,例如房间数楼层等,构成一个含有多个变量的模型,模型中的特征为( x1,x2,..., ...

  10. Uip学习简介及网址

    http://www.ichanging.org/uip-stm32.html http://www.ichanging.org/share/ http://bbs.eeworld.com.cn/th ...