您当前的位置:首页 > 电脑百科 > 程序开发 > 语言 > JAVA

java遍历文件的几种方法

时间:2019-12-10 10:15:18  来源:  作者:

JAVA中遍历目录下的所有文件,很多人第一个想到的是用File.listFiles方法递归. 然而这并不是最好的方法, 这里跟几个其他的方法做一个对比.


 

  1. 自己写函数递归
  2. google的guava工具包
  3. common io工具包
  4. jdk自带的nio Files工具类
package test.walkfile;

import java.io.File;
import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.Collection;
import java.util.concurrent.ConcurrentSkipListSet;

import org.Apache.commons.io.FileUtils;
import org.apache.commons.io.filefilter.TrueFileFilter;

import com.google.common.io.Files;

import util.TimeUtil;

public class WalkFile {

	private static final String rootPath = "D:\";

	public static void main(String[] args) throws IOException {
		Collection<File> res = new ConcurrentSkipListSet<>();
		File root = new File(rootPath);

		TimeUtil.timeStart("byFunction");
		byFunction(root, res);
		System.out.println(res.size());
		TimeUtil.timeEnd("byFunction");
		res.clear();

		TimeUtil.timeStart("guavaBreadthFirst");
		guavaBreadthFirst(root, res);
		System.out.println(res.size());
		TimeUtil.timeEnd("guavaBreadthFirst");
		res.clear();

		TimeUtil.timeStart("guavaDepthFirst");
		guavaDepthFirst(root, res);
		System.out.println(res.size());
		TimeUtil.timeEnd("guavaDepthFirst");
		res.clear();

		TimeUtil.timeStart("byCommonio");
		byCommonio(root, res);
		System.out.println(res.size());
		TimeUtil.timeEnd("byCommonio");
		res.clear();

		TimeUtil.timeStart("byJdkFiles");
		byJdkFiles(root, res);
		System.out.println(res.size());
		TimeUtil.timeEnd("byJdkFiles");
		res.clear();

	}

	/**
	 * 自己写算法遍历文件.
	 * 
	 * @param root
	 * 根路径
	 * @param allFiles
	 * 遍历结果集合
	 */
	private static void byFunction(File root, Collection<File> allFiles) {
		if (root == null || !root.exists()) {
			return;
		}
		if (root.isFile()) {
			allFiles.add(root);
		} else {
			File[] listFiles = root.listFiles();
			if (listFiles != null) {
				for (File childFile : listFiles) {
					byFunction(childFile, allFiles);
				}
			}
		}
	}

	/**
	 * guava 广度优先遍历文件.
	 * 
	 * @param root
	 * 根路径
	 * @param allFiles
	 * 遍历结果集合
	 */
	private static void guavaBreadthFirst(File root, Collection<File> allFiles) {
		Iterable<File> files = Files.fileTraverser().breadthFirst(root);
		files.forEach(f -> allFiles.add(f));
	}

	/**
	 * guava 深度优先遍历文件.
	 * 
	 * @param root
	 * 根路径
	 * @param allFiles
	 * 遍历结果集合
	 */
	private static void guavaDepthFirst(File root, Collection<File> allFiles) {
		Iterable<File> files = Files.fileTraverser().depthFirstPostOrder(root);
		files.forEach(f -> allFiles.add(f));
	}

	/**
	 * 通过common io工具包遍历文件.
	 * 
	 * @param root
	 * 根路径
	 * @param allFiles
	 * 遍历结果集合
	 */
	private static void byCommonio(File root, Collection<File> allFiles) {
		allFiles.addAll(FileUtils.listFiles(root, TrueFileFilter.INSTANCE, TrueFileFilter.INSTANCE));
	}

	/**
	 * 通过jdk的nio Files工具类遍历文件.
	 * 
	 * @param root
	 * 根路径
	 * @param allFiles
	 * 遍历结果集合
	 * @throws IOException
	 * IO异常
	 */
	private static void byJdkFiles(File root, Collection<File> allFiles) throws IOException {
		java.nio.file.Files.walkFileTree(root.toPath(), new SimpleFileVisitor<Path>() {
			@Override
			public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
				allFiles.add(file.toFile());
				return super.visitFile(file, attrs);
			}

			@Override
			public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
				return FileVisitResult.CONTINUE;
			}

		});
	}
}

程序执行结果如下:

152058
byFunction:6584 ms
178667
guavaBreadthFirst:5539 ms
178667
guavaDepthFirst:5153 ms
152058
byCommonio:6543 ms
152058
byJdkFiles:2272 ms

执行3次结果统计:

java遍历文件的几种方法

3次执行时间

jdk自带的Files类比自己递归节约了: (6443 - 2483)÷6443 = 61%的时间. 有些情况下甚至可以节约80%以上的时间. 所以还有什么理由再去自己写算法呢?

除了遍历文件,还有复制文件也是如此. jdk nio的Files工具类用时大概是普通buffer数组方式的1/3, FileChannel和Files差不多一样快.

当性能想要大幅提高的时候,先去java类库找有没有合适的工具类.如果没有再考虑其他jar包. 另外发现,common的jar包一般性能不是很好, 可能偏重于可靠性, google的工具包要好一些.



Tags:java   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
面向对象的特征之一封装 面向对象的特征之二继承 方法重写(override/overWrite) 方法的重载(overload)和重写(override)的区别: 面向对象特征之三:多态 Instanceof关键字...【详细内容】
2021-12-28  Tags: java  点击:(2)  评论:(0)  加入收藏
一、Redis使用过程中一些小的注意点1、不要把Redis当成数据库来使用二、Arrays.asList常见失误需求:把数组转成list集合去处理。方法:Arrays.asList 或者 Java8的stream流式处...【详细内容】
2021-12-27  Tags: java  点击:(3)  评论:(0)  加入收藏
文章目录 如何理解面向对象编程? JDK 和 JRE 有什么区别? 如何理解Java中封装,继承、多态特性? 如何理解Java中的字节码对象? 你是如何理解Java中的泛型的? 说说泛型应用...【详细内容】
2021-12-24  Tags: java  点击:(5)  评论:(0)  加入收藏
1、通过条件判断给变量赋值布尔值的正确姿势// badif (a === &#39;a&#39;) { b = true} else { b = false}// goodb = a === &#39;a&#39;2、在if中判断数组长度不为零...【详细内容】
2021-12-24  Tags: java  点击:(6)  评论:(0)  加入收藏
Java与Lua相互调用案例比较少,因此项目使用需要做详细的性能测试,本内容只做粗略测试。目前已完成初版Lua-Java调用框架开发,后期有时间准备把框架进行抽象,并开源出来,感兴趣的...【详细内容】
2021-12-23  Tags: java  点击:(11)  评论:(0)  加入收藏
传统游戏项目一般使用TCP协议进行通信,得益于它的稳定和可靠,不过在网络不稳定的情况下,会出现丢包严重。不过近期有不少基于UDP的应用层协议,声称对UDP的不可靠进行了改造,这意...【详细内容】
2021-12-23  Tags: java  点击:(12)  评论:(0)  加入收藏
文章目录1、Quartz1.1 引入依赖<dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> <version>2.3.2</version></dependency>...【详细内容】
2021-12-22  Tags: java  点击:(12)  评论:(0)  加入收藏
Java从版本5开始,在 java.util.concurrent.locks包内给我们提供了除了synchronized关键字以外的几个新的锁功能的实现,ReentrantLock就是其中的一个。但是这并不意味着我们可...【详细内容】
2021-12-17  Tags: java  点击:(11)  评论:(0)  加入收藏
一、概述final是Java关键字中最常见之一,表示“最终的,不可更改”之意,在Java中也正是这个意思。有final修饰的内容,就会变得与众不同,它们会变成终极存在,其内容成为固定的存在。...【详细内容】
2021-12-15  Tags: java  点击:(17)  评论:(0)  加入收藏
1、问题描述关于java中的日志管理logback,去年写过关于logback介绍的文章,这次项目中又优化了下,记录下,希望能帮到需要的朋友。2、解决方案这次其实是碰到了一个问题,一般的情况...【详细内容】
2021-12-15  Tags: java  点击:(19)  评论:(0)  加入收藏
▌简易百科推荐
面向对象的特征之一封装 面向对象的特征之二继承 方法重写(override/overWrite) 方法的重载(overload)和重写(override)的区别: 面向对象特征之三:多态 Instanceof关键字...【详细内容】
2021-12-28  顶顶架构师    Tags:面向对象   点击:(2)  评论:(0)  加入收藏
一、Redis使用过程中一些小的注意点1、不要把Redis当成数据库来使用二、Arrays.asList常见失误需求:把数组转成list集合去处理。方法:Arrays.asList 或者 Java8的stream流式处...【详细内容】
2021-12-27  CF07    Tags:Java   点击:(3)  评论:(0)  加入收藏
文章目录 如何理解面向对象编程? JDK 和 JRE 有什么区别? 如何理解Java中封装,继承、多态特性? 如何理解Java中的字节码对象? 你是如何理解Java中的泛型的? 说说泛型应用...【详细内容】
2021-12-24  Java架构师之路    Tags:JAVA   点击:(5)  评论:(0)  加入收藏
大家好!我是老码农,一个喜欢技术、爱分享的同学,从今天开始和大家持续分享JVM调优方面的经验。JVM调优是个大话题,涉及的知识点很庞大 Java内存模型 垃圾回收机制 各种工具使用 ...【详细内容】
2021-12-23  小码匠和老码农    Tags:JVM调优   点击:(12)  评论:(0)  加入收藏
前言JDBC访问Postgresql的jsonb类型字段当然可以使用Postgresql jdbc驱动中提供的PGobject,但是这样在需要兼容多种数据库的系统开发中显得不那么通用,需要特殊处理。本文介绍...【详细内容】
2021-12-23  dingle    Tags:JDBC   点击:(13)  评论:(0)  加入收藏
Java与Lua相互调用案例比较少,因此项目使用需要做详细的性能测试,本内容只做粗略测试。目前已完成初版Lua-Java调用框架开发,后期有时间准备把框架进行抽象,并开源出来,感兴趣的...【详细内容】
2021-12-23  JAVA小白    Tags:Java   点击:(11)  评论:(0)  加入收藏
Java从版本5开始,在 java.util.concurrent.locks包内给我们提供了除了synchronized关键字以外的几个新的锁功能的实现,ReentrantLock就是其中的一个。但是这并不意味着我们可...【详细内容】
2021-12-17  小西学JAVA    Tags:JAVA并发   点击:(11)  评论:(0)  加入收藏
一、概述final是Java关键字中最常见之一,表示“最终的,不可更改”之意,在Java中也正是这个意思。有final修饰的内容,就会变得与众不同,它们会变成终极存在,其内容成为固定的存在。...【详细内容】
2021-12-15  唯一浩哥    Tags:Java基础   点击:(17)  评论:(0)  加入收藏
1、问题描述关于java中的日志管理logback,去年写过关于logback介绍的文章,这次项目中又优化了下,记录下,希望能帮到需要的朋友。2、解决方案这次其实是碰到了一个问题,一般的情况...【详细内容】
2021-12-15  软件老王    Tags:logback   点击:(19)  评论:(0)  加入收藏
本篇文章我们以AtomicInteger为例子,主要讲解下CAS(Compare And Swap)功能是如何在AtomicInteger中使用的,以及提供CAS功能的Unsafe对象。我们先从一个例子开始吧。假设现在我们...【详细内容】
2021-12-14  小西学JAVA    Tags:JAVA   点击:(22)  评论:(0)  加入收藏
最新更新
栏目热门
栏目头条