java高效复制文件并移动_Java 7:复制和移动文件和目录
java高效复制文件并移动
路径对象
路径对象代表可能包含或不包含文件的目录序列。 有三种方法构造Path对象:
- FileSystems.getDefault()。getPath(字符串优先,字符串…更多)
- Paths.get(String path,String…更多),调用FileSystems.getDefault()。getPath的便捷方法
- 在java.io.File对象上调用toPath方法
从现在开始,在所有示例中,我们将使用Paths.get方法。 以下是创建Path对象的一些示例:
//Path string would be "/foo"
Paths.get("/foo");
//Path string "/foo/bar"
Paths.get("/foo","bar");
要操作Path对象,可以使用Path.resolve和Path.relativize方法。 这是使用Path.resolve的示例:
//This is our base path "/foo"
Path base = Paths.get("/foo");
//filePath is "/foo/bar/file.txt" while base still "/foo"
Path filePath = base.resolve("bar/file.txt");
使用Path.resolve方法会将给定的String或Path对象追加到调用Path的末尾,除非给定的String或Path表示绝对路径,否则将返回给定的路径,例如:
Path path = Paths.get("/foo");
//resolved Path string is "/usr/local"
Path resolved = path.resolve("/usr/local");
Path.relativize以相反的方式工作,返回一个新的相对路径,如果根据调用的Path解析该路径,则会得到相同的Path字符串。 这是一个例子:
// base Path string "/usr"Path base = Paths.get("/usr");// foo Path string "/usr/foo"Path foo = base.resolve("foo");// bar Path string "/usr/foo/bar"Path bar = foo.resolve("bar");// relative Path string "foo/bar"Path relative = base.relativize(bar);
Path类上另一个有用的方法是Path.getFileName,该方法返回此Path对象表示的最远元素的名称,该名称是实际文件或目录。 例如:
//assume filePath constructed elsewhere as "/home/user/info.txt"
//returns Path with path string "info.txt"
filePath.getFileName()//now assume dirPath constructed elsewhere as "/home/user/Downloads"
//returns Path with path string "Downloads"
dirPath.getFileName()
在下一节中,我们将研究如何将Path.resolve和Path.relativize与Files类一起使用来复制和移动文件。
文件类
Files类由使用Path对象处理文件和目录的静态方法组成。 尽管Files类中有50多个方法,但目前我们仅讨论复制和移动方法。
复制文件
要将一个文件复制到另一个文件,您可以使用(对名称的任何猜测?)Files.copy方法–非常简洁(没有路径的内部类)的copy(路径源,Path目标,CopyOption…选项),我们确定它是Java吗? options参数是枚举,用于指定应如何复制文件。 (实际上有两个不同的Enum类,LinkOption和StandardCopyOption,但是都实现CopyOption接口。)这是Files.copy的可用选项列表:
- LinkOption.NOFOLLOW_LINKS
- StandardCopyOption.COPY_ATTRIBUTES
- StandardCopyOption.REPLACE_EXISTING
还有一个StandardCopyOption.ATOMIC_MOVE枚举,但是如果指定了此选项,则抛出UsupportedOperationException。 如果未指定任何选项,则默认为在目标文件存在或为符号链接的情况下引发错误。 如果路径对象是目录,那么将在目标位置中创建一个空目录。 (请稍等!在引言中没有说我们可以复制目录的全部内容吗?答案仍然是肯定的,而且即将到来!)这是使用Path使用Path对象将文件复制到另一个文件的示例.resolve和Path.relativize方法:
Path sourcePath ...Path basePath ...Path targetPath ...Files.copy(sourcePath, targetPath.resolve(basePath.relativize(sourcePath));
移动文件
移动文件同样简单明了–移动(路径源,路径目标,CopyOption…选项);
可用的StandardCopyOptions枚举是:
- StandardCopyOption.REPLACE_EXISTING
- StandardCopyOption.ATOMIC_MOVE
如果使用StandardCopyOption.COPY_ATTRIBUTES调用Files.move,则会引发UnsupportedOperationException。 可以在空目录上调用Files.move,或者如果它不需要移动目录内容,例如重新命名,则调用将成功,否则将引发IOException(我们将在下一节中介绍如何移动非空目录)。 如果目标文件已经存在,则默认为引发Exception。 如果源是符号链接,则链接本身将被移动,而不是链接的目标。 这是Files.move的示例,再次使用Path.relativize和Path.resolve方法:
Path sourcePath ...Path basePath ...Path targetPath ...Files.move(sourcePath, targetPath.resolve(basePath.relativize(sourcePath));
复制和移动目录
Files.walkFileTree是在Files类中找到的更有趣和有用的方法之一。 walkFileTree方法执行文件树的深度优先遍历。 有两个签名:
- walkFileTree(路径开始,设置选项,int maxDepth,FileVisitor访问者)
- walkFileTree(路径开始,FileVisitor访问者)
Files.walkFileTree的第二个选项使用EnumSet.noneOf(FileVisitOption.class)和Integer.MAX_VALUE调用第一个选项。 在撰写本文时,只有一个文件访问选项– FOLLOW_LINKS。 FileVisitor是一个接口,其中定义了四个方法:
- preVisitDirectory(T dir,BasicFileAttributes attrs)在遍历所有整数之前调用目录。
- visitFile(T file,BasicFileAttributes attrs)调用目录中的文件。
- postVisitDirectory(T dir,IOException exc)仅在遍历所有文件和子目录之后才调用。
- visitFileFailed(T file,IOException exc)调用了无法访问的文件
所有方法都返回四个可能的FileVisitResult枚举之一:
- FileVistitResult.CONTINUE
- FileVistitResult.SKIP_SIBLINGS(继续而不遍历目录或文件的同级)
- FileVistitResult.SKIP_SUBTREE(继续而不遍历目录内容)
- FileVistitResult.TERMINATE
为了使生活更轻松,有一个默认的FileVisitor实现,即SimpleFileVisitor(validate参数不为null并返回FileVisitResult.CONTINUE),可以将其子类化,您可以覆盖您需要使用的方法。 让我们看一个用于复制整个目录结构的基本示例。
复制目录树示例
让我们看一下扩展用于复制目录树的SimpleFileVisitor的类(为清晰起见,省略了一些详细信息):
public class CopyDirVisitor extends SimpleFileVisitor<Path> {private Path fromPath;private Path toPath;private StandardCopyOption copyOption = StandardCopyOption.REPLACE_EXISTING;....@Overridepublic FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {Path targetPath = toPath.resolve(fromPath.relativize(dir));if(!Files.exists(targetPath)){Files.createDirectory(targetPath);}return FileVisitResult.CONTINUE;}@Overridepublic FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {Files.copy(file, toPath.resolve(fromPath.relativize(file)), copyOption);return FileVisitResult.CONTINUE;}
}
在第9行中,将遍历源文件“ fromPath”中的每个目录,并在目标“ toPath”中创建每个目录。 在这里,我们可以看到Path对象在处理目录和文件方面的强大功能。 随着代码深入目录结构,只需分别在fromPath和toPath对象上调用relativize和resolve即可构造正确的Path对象。 我们根本不需要知道我们在目录树中的位置,因此不需要繁琐的StringBuilder操作即可创建正确的路径。 在第17行,我们看到用于将文件从源目录复制到目标目录的Files.copy方法。 接下来是删除整个目录树的简单示例。
删除目录树示例
在此示例中,SimpleFileVisitor已被子类化,用于删除目录结构:
public class DeleteDirVisitor extends SimpleFileVisitor<Path> {@Overridepublic FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {Files.delete(file);return FileVisitResult.CONTINUE;}@Overridepublic FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {if(exc == null){Files.delete(dir);return FileVisitResult.CONTINUE;}throw exc;}
}
如您所见,删除是一个非常简单的操作。 只需删除找到的每个文件,然后在退出时删除目录即可。
将Files.walkFileTree与Google Guava结合
前两个示例虽然有用,但非常“香草”。 让我们看一下另外两个示例,它们结合了Google Gauva Function和Predicate接口,更具创意。
public class FunctionVisitor extends SimpleFileVisitor<Path> {Function<Path,FileVisitResult> pathFunction;public FunctionVisitor(Function<Path, FileVisitResult> pathFunction) {this.pathFunction = pathFunction;}@Overridepublic FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {return pathFunction.apply(file);}
}
在这个非常简单的示例中,我们将SimpleFileVisitor子类化,以将Function对象作为构造函数参数,并且在遍历目录结构时,将该函数应用于每个文件。
public class CopyPredicateVisitor extends SimpleFileVisitor<Path> {private Path fromPath;private Path toPath;private Predicate<Path> copyPredicate;public CopyPredicateVisitor(Path fromPath, Path toPath, Predicate<Path> copyPredicate) {this.fromPath = fromPath;this.toPath = toPath;this.copyPredicate = copyPredicate;}@Overridepublic FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {if (copyPredicate.apply(dir)) {Path targetPath = toPath.resolve(fromPath.relativize(dir));if (!Files.exists(targetPath)) {Files.createDirectory(targetPath);}return FileVisitResult.CONTINUE;}return FileVisitResult.SKIP_SUBTREE;}@Overridepublic FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {Files.copy(file, toPath.resolve(fromPath.relativize(file)));return FileVisitResult.CONTINUE;}
}
在此示例中,CopyPredicateVisitor接收一个Predicate对象,并且基于返回的布尔值,不会复制部分目录结构。 我想指出的是,前面两个示例(除了有用性之外)确实可以在本文后面提供的源代码中进行单元测试。
DirUtils
在到目前为止所讨论的所有内容的基础上,我无法抗拒创建实用程序类DirUtils的机会, 该类是使用以下提供以下方法的目录的抽象:
//deletes all files but leaves the directory tree in placeDirUtils.clean(Path sourcePath);//completely removes a directory treeDirUtils.delete(Path sourcePath);//replicates a directory treeDirUtils.copy(Path sourcePath, Path targetPath);//not a true move but performs a copy then a delete of a directory treeDirUtils.move(Path sourcePath, Path targetPath);//apply the function to all files visitedDirUtils.apply(Path sourcePath,Path targetPath, Function function);
虽然我不愿意说它已经可以生产了,但是写起来很有趣。
结论
这就包装了java.nio.file包提供的新的复制和移动功能。 我个人认为它非常有用,并且可以减轻使用Java中文件的痛苦。 有关符号链接,流复制方法,DirectoryStreams等的更多内容,请务必坚持。 谢谢你的时间。 一如既往地欢迎提出意见和建议。
参考: Java 7的新增功能: JCG合作伙伴提供的 文件和目录的复制和移动 比尔·贝杰克(Bill Bejeck)在“ 编码随机思想”博客上。
翻译自: https://www.javacodegeeks.com/2012/02/java-7-copy-and-move-files-and.html
java高效复制文件并移动
java高效复制文件并移动_Java 7:复制和移动文件和目录相关推荐
- java高效获取内部类属性值_Java高级特性:内部类
内部类是什么 内部类是指在一个外部类的内部再定义一个类.内部类作为外部类的一个成员,并且依附于外部类而存在的.内部类可为静态,可用protected和private修饰(而外部类只能使用public和 ...
- java通道 硬件通道 如何联系_Java NIO5:通道和文件通道
一.通道是什么 通道式(Channel)是java.nio的第二个主要创新.通道既不是一个扩展也不是一项增强,而是全新的.极好的Java I/O示例,提供与I/O服务的直接连接.Channel用于在字 ...
- java导出excel 打不开_Java使用POI生成Excel文件后打不开的问题
在实际的工作中,有时会遇到获取数据后需要存入Excel文件的情况.但是,在生成Excel文件后,发现无法正常打开该文件. 例如:以当前的时间点为文件名,新生成一个Excel文件.先来看看下面一段代码. ...
- java递归实现 堆的删除_java 递归实现删除或查询指定目录下的全部文件
/** * 递归列举盘符下的全部文件的名称,如E:\HeartIsland * * @author HeartIsland * */ public class FileListDemo { /** * ...
- java中 复制到下一行_java代码复制到下一行
java代码复制到下一行 [2021-02-10 13:04:40] 简介: php去除nbsp的方法:首先创建一个PHP代码示例文件:然后通过"preg_replace("/( ...
- java解析各种文档格式_java读取各类型的文件
用到的几个包 bcmail-jdk14-132.jar/bcprov-jdk14-132.jar/checkstyle-all-4.2.jar/FontBox-0.1.0-dev.jar/lucene ...
- java 多个类共用属性_java中读写Properties属性文件公用方法详解
前言 大家都知道Java中有个比较重要的类Properties(Java.util.Properties),主要用于读取Java的配置文件,各种语言都有自己所支持的配置文件,配置文件中很多变量是经常改 ...
- java点击图片发出声音_Java 中图片和声音文件的加载
/* * 本程序实现以下效果: * 1.界面显示一个按钮,按钮初始为红色. * 2.将鼠标移到按钮上时,按钮呈蓝色. * 3.点击鼠标,有声音效果. * 4.鼠标离开按钮时,按钮恢复成红色. */ i ...
- java给txt文件写入内容_java代码 如何向TXT文件写入内容?
展开全部 向txt文件写入内容基本思路就是获得一个62616964757a686964616fe59b9ee7ad9431333337613134file对象,新建一个txt文件,打开I/O操作流,使 ...
- java下载文件到服务器_java代码实现上传文件到文档服务器、下载文档服务器文件...
需要完成下载->修改->上传这三个步骤 平台有提供对应的api吗? /** 首先我们来理解下关于文档的api 文档相关api都在这2个package下面 package :com.just ...
最新文章
- clear arp-cache作用_肇庆Sylvin-2900-75-Clear
- 太真实!当程序员接手了新项目...... | 每日趣闻
- 安装Phoenix时./sqlline.py执行报错File ./sqlline.py, line 27, in module import argparse ImportError: No ...
- zabbix监控haproxy
- phonegap html 缩放,phonegap常用事件总结(必看篇)
- java字节流分为_Java文件流可分为字节流和字符流。
- python前端调用后端模型_前端调用后端的方法(基于restful接口的mvc架构)
- Serv-u6.0提权新玩法
- Eclipse maven构建springmvc项目
- 【20211009】【数学基础】极值点、驻点、拐点的区别和联系
- python制作圆形按钮_圆形按钮tkinter python
- Axure热区的使用
- 中南林业科技大学的计算机研究生分数线,2020中南林业科技大学研究生分数线(以及历年复试)...
- AD使用技巧——如何改变布线走线的角度
- C语言简单五子棋两人/五子棋人机
- mac 下安装swoole
- EXCEL通过IF与COUNTIF嵌套解决多条件筛选需要注意的问题
- python玩王者荣耀皮肤_python 王者荣耀皮肤高清图片下载 附源码
- 发票、司法、扶贫,政务应用已成区块链率先落地领域?
- 【论文精读】AVP-Loc: Surround View Localization and Relocalization Based on HD VectorMap for AVP
热门文章
- 干货!sqlserver数据库所有知识点总结整理,含代码(挺全的)
- 2017 年编程语言排行榜:Python 排第一
- java实现加密电话号码,有具体的加密流程注释
- SpringCloudStream
- JAVA多线程总结(笔记)
- ubuntu 16.4 安装postgreSQL,使C++链接到数据库
- impdp导入mysql_Oracle数据库的impdp导入操作以及dba_directories使用方法
- 如何写登录的记住账号
- twitter自定义api_为Twitter4j创建自定义SpringBoot Starter
- java高级教程_高级Java教程