热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

IO系列之File

1File类1.1目录列表器在这里我主要是参考ThinkinJava的内容从而做的一些总结以及扩展。Java中的IO流的设计应该说是Java中最经典的,最学院式的设计,包括它的整体

1 File类


1.1 目录列表器

在这里我主要是参考Think in Java的内容从而做的一些总结以及扩展。Java中的IO流的设计应该说是Java中最经典的,最学院式的设计,包括它的整体架构设计以及代码的构造。 
现在让我们开始进行文件过滤吧。说到这里,说一下这个File类,从类名上看,它表示文件的意思,但是这个意思却不是准确的表达它的含义,FilePath应该来说更加的符合,它表示的就是文件的路径。好了,让我们看看当前的文件目录吧。
技术分享图片

这个就是当前文件所在的目录。 
好了,让我先列出所有的文件列表吧。

package cn.czg.io;
import java.io.File;
/**
* 目录列表器
*/
public class DirListDemo {
public static void main(String[] args) {
/** 文件表示当前目录*/
File filePath
=new File(".");
/** 当前目录的文件名称组成一个String[] 数组*/
String[] list
= filePath.list();
for (String listDir:list) {
System.out.println(listDir);
/**
* .idea
* pom.xml
* spring40parent.iml
* src
* target
* 测试.java
*/
}
}
}

上面的输出结果和文件的目录是一致的。不带参数的list()方法的功能就是返回一个该目录下的文件名的String数组。

public String[] list() {
SecurityManager security
= System.getSecurityManager();
if (security != null) {
security.checkRead(path);
}
if (isInvalid()) {
return null;
}
return fs.list(this);
}

security是一个安全管理器对象,第一个判断是判断安全管理器是否为空,这个目的是为了分配文件的操作权限,比如读写的权限,第二个判断则是判断文件的路径时候合理或者存在。关于安全管理器我希望在有时间的时候作为单独的一个系列来研究下它的源码。在这里我希望不要深究。

1.2 文件过滤器

在大多的时候我们还是希望得到我们想要的文件,比如后缀是.java结尾的文件,在jdk中,存在着专门的一个接口,就是FilenameFilter.它表示的就是文件过滤器。

@FunctionalInterface
public interface FilenameFilter {
boolean accept(File dir, String name);
}

当且仅当该文件名称包含在文件列表中,则返回true,其他的返回false.好了,让我们实践一把吧。 
在操作之前,我们来看看file.list()的api
 技术分享图片

大家可以清楚的看到,下面的list()方法带有参数,参数是一个filter,即文件过滤器。 
请看如下的代码:

/**
* 目录列表器
*/
public class DirListDemo {
public static void main(String[] args) {
/** 文件表示当前目录*/
File filePath
=new File(".");
/** 当前目录的文件名称组成一个String[] 数组*/
//String[] list = filePath.list();
// list方法包含了所有的文件的名称
// 如果要调用含有参数的list方法,此时就需要一个FilenameFilter的实现类,并且实现正则匹配
MyFilenameFilter filter=new MyFilenameFilter(".java");
String[] list
= filePath.list(filter);
for (String dirList:list) {
System.out.println(dirList);
}
}
}
class MyFilenameFilter implements FilenameFilter{
private String regex;
public MyFilenameFilter(String regex) {
this.regex=regex;
}
@Override
public boolean accept(File dir, String name) {
return name.endsWith(regex);
}
}

打印结果毫无疑问的将后缀为Java的文件帅选出来,好了,接着我们可以对刚才的代码进行优化,让它看起来比较完美。 
优化一 匿名内部类:

public class DirListDemo3 {
public static void main(String[] args) {
/** 文件表示当前目录*/
File filePath
=new File(".");
String[] list
= filePath.list(filter(".java"));
for (String dirList:list) {
System.out.println(dirList);
}
}
public static FilenameFilter filter(String regex){
return new FilenameFilter() {
private String regexs=regex;
@Override
public boolean accept(File dir, String name) {
return name.endsWith(regexs);
}
};
}
}

大家可以看到,上述的FilenameFilte作为方法的返回值进行了传递,此时FilenameFilte掺杂在DirListDemo3中,所以我们直接将FilenameFilte作为方法的参数直接传递也是可以的,这样也是降低了耦合: 
优化二:FilenameFilte作为参数传递:

public class DirListDemo {
public static void main(String[] args) {
/** 文件表示当前目录*/
File filePath
=new File(".");
String regex
=".java";
String[] list
= filePath.list(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return name.endsWith(regex);
}
});
for (String dirList:list) {
System.out.println(dirList);
}
}
}


1.3 目录实用工具

现在我的需求就是列出当前文件下的所有的文件或者文件夹 
看到这里我们很容易想到递归的操作方式,确实如此,本例也是使用的递归的算法来完成

 

public class Directory2 {
public static void main(String[] args) {
File file
=new File(".");
list(file);
}
public static void list(File file){
if(file.isDirectory()){
File[] files
= file.listFiles();
if(files!=null){
for (int i=0;i){
// 此时files[i]表示的是一个文件或者文件目录
//采用递归算法,直接调用list()方法,将files[i]作为参数进行传递
list(files[i]);
}
}
}
System.out.println(file);
}
}

 

在Think in java中,封装了一个工具类来完成相同的功能。但是功能要比我上述的写的完全要多。我做了相应的修改,使得代码变得可读性较好

package cn.czg.io;
import java.io.File;
import java.io.FilenameFilter;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class Directory {
/**
* 该方法返回一个File[]数组,和我们之前的目录列表器是相同的,
* 通过特定的形式返回特定的文件
*
@param dir
*
@param regex
*
@return
*/
public static File[] local(File dir,final String regex){
return dir.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return name.endsWith(regex);
}
});
}
/**
* 该方法和上述的local()方法是方法的重载,只不过此时传递的参数均为字符串,
* 第一个参数为文件路径的目录的字符串表达形式,第二个参数相同
* 最后调用第一个local()方法
*
@param path
*
@param regex
*
@return
*/
public static File[] local(String path,final String regex){
return local(new File("path"),regex);
}
/**
* 定义一个静态内部类TreeInfo,表示的是文件目录树,实现Iterable,实现此接口的类就可以
* 成为forech的目标
*/
public static class TreeInfo implements Iterable{
/**
* 定义两个list集合,分别是files(文件list)以及dirs(目录list)
*/
public List files=new ArrayList<>();
public List dirs=new ArrayList<>();
/**
* 覆盖iterator()方法,返回一个File的比较器
*
@return
*/
@Override
public Iterator iterator() {
return files.iterator();
}
void addAll(TreeInfo other){
/**
* 将集合files和集合dirs全部添加到对应的list当中
*/
files.addAll(other.files);
dirs.addAll(other.dirs);
}
@Override
public String toString() {
return "TreeInfo{" +
"files=" + files +
", dirs=" + dirs +
‘}‘;
}
}
/**
* 在这里分析下,TreeInfo表示的就是目录树对象,有两个字段
* files和dirs,这两个集合分别存储文件和目录,而recurseDirs()方法返回的就是TreeInfo对象
* 这个对象保存了文件和目录,walk()的作用就是执行。
*
@param start
*
@param regex
*
@return
*/
public static TreeInfo walk(String start,String regex){
return recurseDirs(new File(start),regex);
}
public static TreeInfo walk(File start,String regex){
return recurseDirs(start,regex);
}
public static TreeInfo walk(File start){
return recurseDirs(start,".*");
}
public static TreeInfo walk(String start){
return recurseDirs(new File(start),".*");
}
/**
*
*
@param startDirs
*
@param regex
*
@return
*/
static TreeInfo recurseDirs(File startDirs, String regex) {
TreeInfo result
=new TreeInfo();
for (File item:startDirs.listFiles()) {
if(item.isDirectory()){
result.dirs.add(item);
/**
* 递归方法的出口,如果该文件下存在子文件或者子文件夹,
* 继续调用recurseDirs()方法,返回的TreeInfo目录树对象添加到
* list集合当中
*/
result.addAll(recurseDirs(item,regex));
}
else {
/**
* 否则,直接帅选
*/
if(item.getName().endsWith(regex))
result.files.add(item);
}
}
return result;
}
public static void main(String[] args) {
File[] local
= local(new File("."), ".java");
for (File fs:local) {
System.out.println(fs);
}
}
}

 


推荐阅读
  • 利用Selenium与ChromeDriver实现豆瓣网页全屏截图
    本文介绍了一种使用Selenium和ChromeDriver结合Python代码,轻松实现对豆瓣网站进行完整页面截图的方法。该方法不仅简单易行,而且解决了新版Selenium不再支持PhantomJS的问题。 ... [详细]
  • 解决TensorFlow CPU版本安装中的依赖问题
    本文记录了在安装CPU版本的TensorFlow过程中遇到的依赖问题及解决方案,特别是numpy版本不匹配和动态链接库(DLL)错误。通过详细的步骤说明和专业建议,帮助读者顺利安装并使用TensorFlow。 ... [详细]
  • 通常情况下,修改my.cnf配置文件后需要重启MySQL服务才能使新参数生效。然而,通过特定命令可以在不重启服务的情况下实现配置的即时更新。本文将详细介绍如何在线调整MySQL配置,并验证其有效性。 ... [详细]
  • Python自动化测试入门:Selenium环境搭建
    本文详细介绍如何在Python环境中安装和配置Selenium,包括开发工具PyCharm的安装、Python环境的设置以及Selenium包的安装方法。此外,还提供了编写和运行第一个自动化测试脚本的步骤。 ... [详细]
  • 嵌入式开发环境搭建与文件传输指南
    本文详细介绍了如何为嵌入式应用开发搭建必要的软硬件环境,并提供了通过串口和网线两种方式将文件传输到开发板的具体步骤。适合Linux开发初学者参考。 ... [详细]
  • 探索新一代API文档工具,告别Swagger的繁琐
    对于后端开发者而言,编写和维护API文档既繁琐又不可或缺。本文将介绍一款全新的API文档工具,帮助团队更高效地协作,简化API文档生成流程。 ... [详细]
  • 本文探讨了在构建应用程序时,如何对不同类型的数据进行结构化设计。主要分为三类:全局配置、用户个人设置和用户关系链。每种类型的数据都有其独特的用途和应用场景,合理规划这些数据结构有助于提升用户体验和系统的可维护性。 ... [详细]
  • 气象对比分析
    本文探讨了不同地区和时间段的天气模式,通过详细的图表和数据分析,揭示了气候变化的趋势及其对环境和社会的影响。 ... [详细]
  • 深入解析动态代理模式:23种设计模式之三
    在设计模式中,动态代理模式是应用最为广泛的一种代理模式。它允许我们在运行时动态创建代理对象,并在调用方法时进行增强处理。本文将详细介绍动态代理的实现机制及其应用场景。 ... [详细]
  • 深入理解ExtJS:从入门到精通
    本文详细介绍了ExtJS的功能及其在大型企业前端开发中的应用。通过实例和详细的文件结构解析,帮助初学者快速掌握ExtJS的核心概念,并提供实用技巧和最佳实践。 ... [详细]
  • 本文详细介绍如何在 iOS 7 环境下申请苹果开发者账号,涵盖从访问开发者网站到最终激活账号的完整流程。包括选择个人或企业账号类型、付款方式及注意事项等。 ... [详细]
  • 本文介绍了如何通过Java代码计算一个整数的位数,并展示了多个基础编程示例,包括求和、平均分计算、条件判断等。 ... [详细]
  • 本题要求在一组数中反复取出两个数相加,并将结果放回数组中,最终求出最小的总加法代价。这是一个经典的哈夫曼编码问题,利用贪心算法可以有效地解决。 ... [详细]
  • 本篇文章介绍如何将两个分别表示整数的链表进行相加,并生成一个新的链表。每个链表节点包含0到9的数值,如9-3-7和6-3相加得到1-0-0-0。通过反向处理链表、逐位相加并处理进位,最终再将结果链表反向,即可完成计算。 ... [详细]
  • 本文探讨了C++编程中理解代码执行期间复杂度的挑战,特别是编译器在程序运行时生成额外指令以确保对象构造、内存管理、类型转换及临时对象创建的安全性。 ... [详细]
author-avatar
苦蔷薇1988
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有