操作文件


之前我们所讨论的输入输出流类关心的是文件的内容,而我们在此处要讨论的类关心的是在磁盘上如何储存文件。我将在下文介绍Path接口和Files类,它们是在 JavaSE 7中新添加进来的 它们用起来比自JDK 1.0以来就一直使用的一直使用的File类要方便的多

Path

Path表示的是一个目录名序列,其后还可以跟一个文件名。
  • 首先我们要理解 绝对路径 和 相对路径 的概念
绝对路径和相对路径:
以跟部件开始的路径是绝对路径;否则,就是相对路径。

当指定一个相对文件名(相对路径)时,例如"myfile.txt","mydirectory/myfile.txt"。
则文件位于JAVA虚拟机启动的路径的相对位置

   System.getProperty("user.dir");
//得到JAVA虚拟机启动路径的相对位置
//命令行方式下启动路径就是命令解释器的当前路径
//如果使用集成开发环境,则启动路径由IDE控制


  • 方法
获取路径:
Java.nio.file.Paths 7

static Path get(String first,String ... more);
静态的Paths.get方法接受一个或多个字符串,并将它们用默认文件系统的路径分隔符连接起来
也接受含多个部件构成的单个字符串(例如"E:\\JDK源码\\javax\\lang\\model"

组合/解析路径:

Java.nio.file.Path 7
Path resolve(Path other)
调用p.resolve(q)按照下列规则返回一个路径(Path)
如果q是绝对路径,则结果为q
否则,根据文件系统的规则,将“p后面跟着q”作为结果

Path resolve(String other)
resolve方法有个便捷方式,他接受一个字符串而不是路径

Path resolveSibling(Path other)
Path resolveSibling(String other)
如果other是绝对路径,那么就返回other;否则,返回通过连接this的父路径和other获得的路径

相对于某个路径的绝对路径

Path relativize(Path other)
返回other相对于this的绝对路径
例如:
Path a=Paths.get("E:\\JDK源码\\javax");

Path b=Paths.get("E:\\JDK源码\\javax\\imageio\\plugins");
a.relativize(b);        //结果为 imageio\plugins

Path a=Paths.get("E:\\JDK源码\\javax\\lang\\model");

Path b=Paths.get("E:\\JDK源码\\javax\\imageio\\plugins");
a.relativize(b);        //结果为 ..\..\lang\model, 其中..的含义为a的父目录

//这里可能有些绕,我的建议是自己动手使用它,这样更直观,更容易理解


切割路径

Path getParent()
返回父路径,或者在该路径没有父路径时,返回null
Path getFileName()
返回该路径的最后一个部件,或者在该路径没有任何部件时,返回null
Path getRoot()
返回该路径的跟部件,或者在该路径没有任何跟部件时,返回null

Path类有许多有用的方法用来将路径断开,下面的代码展示了其中部分最有用的方法

Path p = Paths.get("E:","python","LICENSE.txt");
Path parent = p.getParent();
Path file = p.getFileName();
Path root = p.getRoot();
System.out.println(parent);
System.out.println(file);

System.out.println(root);
结果为:
E:\python
LICENSE.txt
E:\

其他方法:
Path normalize()
移除诸如.和..等冗余的路径元素
Path toAbsolutePath()
返回于该路径等价的绝对路径。
toFile()
从该路径中创建一个File对象
//另外File类也有将File转换为Path的方法:to Path()


读写文件


读取文件所有内容:
byte[] bytes = Files.readAllBytes(path);
如果想将文件当作字符串读入,可以在调用readAllBytes之后执行下面代码:
String content =new String(bytes,charset);
但是如果希望将文件当作序列读入,那么可以调用:
List<String> lines = Files.readAllLines(path,charset);//可以用增强for语句读出
相反的,如果希望写出一个字符串到文件中,可以调用:
Files.write(path,content.getBytes(charset));//覆盖原内容
向指定文件追加内容,可以调用:
Files.write(path,content.getBytes(charset,StandardOpenOption.APPEND)) //path路径必须是URL,
// StandardOpenOption枚举类型定义了 options
还可以用下面的语句将一个行的集合写出到文件中
Files.write(path,lines); 

  • 上面这些简便方法适用于处理中等长度的文本文件,如果要处理的文件长度比较大,或者是二进制文件,那么还是应该使用我们所熟知的输入/输出流进行操作。
InputStream in = Files.newInputStream(path);OutputStream out = Files.newOutputStream(path);
Reader in = Files.newBufferedReader(path,charsetName);Writer out = Files.newBufferedWriter(path,charsetName);
这些便捷方法可以将你从处理FileInputStream、FileOutputStream、BufferedReader和BufferedWriter的繁复操作中解脱出来。


创建文件和目录

创建新目录可以调用:
Files.createDirectory(path)
其中,除了最后一个部件外,其他部件必须是已存在的

要创建路径中的中间目录,应该使用:
Files.createDirectories(path)

可以使用下面语句创建一个空文件:
Files.createFile(path);
如果文件已经存在了,那么这个调用就会抛出异常。

复制、移动和删除文件


将文件从一个位置复制到另一个位置可以直接调用:
Files.copy(fromPath,toPath);

移动文件可以调用:
Files.move(fromPath,toPath);
//其本质是复制并删除原文件
// StandardCopyOption枚举类型定义了 options.

如果目标路径已经存在,那么复制或移动将失败。如果想要覆盖已有目标路径,可以使用REPLACE_EXISTING选项。如果想要复制所有文件属性,可以使用COPY_ATTRIBUTES。也可以像下面这样同时选择这两个选项。
Files.copy(fromPath,toPath,StandardCopyOption.REPLACE_EXISTING,
                                            StandardCopyOption.COPY_ATTRIBUTES);

你可以将移动操作定义为原子性的,这样就可以保证要么移动操作完成要么原文件继续保持在原来位置。具体可以使用ATOMIC_MOVE选项来实现:
Files.move(fromPath,toPath,StandardCopyOption.ATOMIC_MOVE);








Comments

Popular posts from this blog

抓包工具Wireshark下载及安装教程

HTTP协议特性

Java中Synchronized的用法