Java中是通过File类来存取文件和路径的。没错,这是一个非常容易混淆的名字,你可能认为它仅仅能够处理文件,实际上它既可以代表了一个特定的文件,又可以代表某个文件夹内的文件名列表。如果它是文件,你可以通过length()方法获取它的大小、通过lastModified()方法最后修改时间,等等;如果它代表文件名列表,则可以用list()得到表示文件名列表的字符串数组,或者用listFiles()方法得到表示子文件列表的File数组。总之,在Java中文件夹和文件已经被统一成一个抽象的概念,只要了解它的原理,使用起来将会感到非常方便。
我们说过,File类的listFiles()方法可以得到表示子文件列表的File数组,如果仅仅想要得到特定的子文件而过滤掉其他的文件,则可以给listFiles()方法加上参数??一个过滤器。
所谓的过滤器,就是一个实现FilenameFilter接口的Java类。所谓接口(interface),就是仅仅定义了行为协议,所有声明实现这个接口的类必须具体实现这个接口的行为。换句话说,接口是一种契约,比如这里FilenameFilter的定义是这样子的:
你看,FolderFilter类通过implements表示对FilenameFilter接口的支持,然后实现了这个接口的accept方法。具体地,在accept方法中,通过传入的dir参数和name参数新建一个File实例,然后通过调用isDirectory()方法判断这个实例是否是文件夹,是则返回True,否则返回False。
注意到这个方法必须和FilenameFilter接口里面声明的一模一样。正因为如此,每次手动输入接口声明既麻烦又容易出错。还是让Eclipse干体力活吧!打开Eclipse,新建一个类,名字为FolderFilter,按下Interfaces文本列表右边的Add按钮,在弹出的对话框中输入FilenameFilter即可。实际上,Eclipse会根据你的输入进行筛选,非常聪明(见图1)。
假设path是一个File类的实例,我们便可以通过File[] subFolders = path.listFiles(new FolderFilter())得到path的子文件夹列表了。
黄糖故事
设计模式(Design Patterns)
建筑工程师Cristopher Alexander总结了建筑中的经验教训,发现有些问题总是一遍又一遍重复出现,当你总结出一套解决这种问题的核心方法以后,你只要放心使用这种解决方法即可,而完全不必再动脑筋想其他的方案。虽然这句话很朴素,但是却成了软件工程中一种举足轻重的方法学?设计模式的指导思想。
我们知道,建筑学有牛顿力学作为辩证的理论根据,只要尊重科学,就不可能设计出坍塌的建筑(即使坍塌,也是材料施工不过关或其他因素造成的)。但是,编写软件却没有这样的理论根据,因为程序只是告诉计算机语法,计算机只要如此这般依计而行,愚忠而已,而没有机制能保证程序的语意符合人类的思想。因此,程序才会有BUG,即使比尔对Windows XP大吼:“我以老祖宗的名义不准你有BUG!”,Windows XP能够领会精神吗?
虽然没有彻底的解决方法,Erich Gamma等四位大师级的计算机科学家通过借鉴建筑学中的模式的概念,创造出软件中的设计模式,通过精心萃取的23个模式,有效解决了软件的设计问题,给程序加上了一定程度的模型语意。具体的,请阅读这“四人帮”(Gang of Four)编写的《Design Patterns》一书。值得一提的是,我们上一回编写的名字解析器就是运用了其中的Factory模式,结构非常漂亮。
顺便说一句,现在支持设计模式的工具也越来越多 ,如果你想有朝一日从Java程序员升级为呼风唤雨的Java构架师,这可是一门必修课哦!
4.正则表达式(Regular Expression)
说起正则表达式,即使不熟悉,你也会觉得非常眼熟。没错,现在的文本编辑软件,无论是UltraEdit还是EditPlus,无一不支持正则表达式。可以说,不支持正则表达式的编辑器肯定是三流货色啦。
理论上,正则表达式等价于有限自动机,能够表达相当丰富的语言,DOS中通配符的能力是无法望其项背的。学过编译原理或者计算机理论的朋友一定很熟悉了,可是,如果从头开讲,恐怕这期所有版面都不够。因此这里推荐你参考Sun免费的Java Tutorial中的Regular Expressions一章,写得很详细。即使你熟悉计算机理论的正则表达式,也建议抽空看一看,因为Java采取的是类Perl风格的语法,和理论书上有些出入。
比如我们要过滤出所有Java源程序。众所周知,Java文件名必须以字母、美元符号或者下划线开头,然后可以由数字、字母、美元符号或者下划线的任意组合,最后扩展名是java。用正则表达式写出来,就是“[a-zA-Z_$][a-zA-Z_$0-9]*\.java”(不含引号)。
其中,[a-zA-Z_$]表示小写字母a至z、大写字母A至Z、美元符号或者下划线任取其一;[a-zA-Z_$0-9]*表示小写字母a至z、大写字母A至Z、美元符号、下划线以及0至9这十个数字的任意组合;“\.java”表示Java源程序的扩展名,由于“.”在Java正则表达式中有特殊意义,所以“\.”才表示一个“.”符号。
当然,Java正则表达式API中还有许多扩充,可以简写为:[a-zA-Z_$][\w$]*\.java。
有了这些知识,我们不难写出支持正则表达式的文件过滤器FileFilter,源代码如下:
public class FileFilter implements FilenameFilter {
private Pattern pattern;
public FileFilter(String regex) {
pattern = Pattern.compile(regex);
}
public boolean accept(File dir, String name) {
File file = new File(dir + "\\" + name);
return pattern.matcher(file.getName()).matches() && file.isFile();
}
}
Java中通过Pattern类来使用正则表达式。在FileFilter的构造函数中,通过把regex参数传递给Pattern的compile()方法,便可以得到一个代表这个正则表达式的实例,之后便可以在accept()方法中调用了。具体地,当且仅当文件名满足正则表达式并且这的确是一个文件时,accept()方法返回True。
5.递归搜索子目录
有了这两个过滤器,递归搜索指定目录中符合正则表达式的文件名就很容易了。先在项目中生成一个包含main方法的ExpZip类,然后添加一个recursiveAppend(File path, ArrayList list, String regex)方法,其中,参数path是指要搜索的文件夹,list是用来返回符合正则表达式的文件名的列表,regex自然是正则表达式了。源代码如下:
private static void recursiveAppend(File path, ArrayList list, String regex) {
// 搜索path文件夹中符合要求的文件并添加到list里。
File[] files = path.listFiles(new FileFilter(regex));
if (files.length > 0) {
for (int i = 0; i < files.length; i++) {
list.add(files[i].getAbsolutePath());
}
}
// 递归搜索path子文件夹。
File[] subFolders = path.listFiles(new FolderFilter());
if (subFolders.length > 0) {
for (int i = 0; i < subFolders.length; i++) {
recursiveAppend(subFolders[i], list, regex);
}
}
}
代码很简单,请参考注释阅读。
Java文件操作(3)
6.ZIP压缩和CRC校验
良好的开端是成功的一半,有了上面的准备,完成主程序也就很容易了。
public static void main(String[] args) {
// 程序出现任何异常都将打印使用信息。
try {
// 记录正则表达式和路径名称。
String regex = args[1];
String targetFolder = args[0];
File path = new File(targetFolder);
ArrayList files = new ArrayList();
// 递归搜索path所指定的文件夹内以及子文件夹内满足合正则表达式。
recursiveAppend(path, files, regex);
if (files.size() == 0) {
System.out.println("找不到任何匹配的文件!");
return;
}
// 把符合正则表达式的文件压缩成ZIP格式并且返回CRC校验值。
FileOutputStream file = new FileOutputStream("Backup.zip");
CheckedOutputStream csum = new CheckedOutputStream(file, new CRC32());
ZipOutputStream zos = new ZipOutputStream(csum);
BufferedOutputStream out = new BufferedOutputStream(zos);
// 为ZIP包添加注释。
zos.setComment("Backup " + regex + " in " + targetFolder);
// 开始压缩。
for (int i = 0; i < files.size(); i++) {
String currentFile = (String) files.get(i);
System.out.println("Writing file " + currentFile);
BufferedReader in = new BufferedReader(new FileReader(currentFile));
zos.putNextEntry(new ZipEntry(currentFile));
int c;
while ((c = in.read()) != -1)
out.write(c);
in.close();
}
out.close();
// 当压缩包关闭以后便可以得到CRC校验值。
System.out.println("CRC校验值:" + csum.getChecksum().getValue());
} catch (Exception e) {
printUsage();
}
}
首先可以看到,整个main函数部分是用一个大的try...catch异常捕获语句容纳起来的,当程序出现任何异常时,我们都认为是用户的参数不正确,便调用printUsage()方法打印使用信息,具体代码从略。
首先通过recursiveAppend()方法递归搜索指定的文件夹内以及子文件夹内满足合正则表达式的文件名,结果将保存在files中。如果有满足条件的文件,则把这些文件压缩成ZIP格式,并添加适当的注释。当压缩包关闭以后便可以得到ZIP包的CRC校验值。
注意,以上这些代码使用的都是Java API内置的功能,如果你在编写的过程中遇到找不到类定义的情况,别忘记使用Eclipse内置的Ctrl+Shift+M自动导入功能。
至此,整个软件全部编写好了。你可以在命令行手动输入把玩一下,或者点击Run菜单的Run...菜单项,配置Eclipse运行的参数如图2所示。

再见
逝者如斯,连载已经四个多月了。小店开张至今得到众多朋友的支持与鼓励,已经有200多位朋友在garychan.3322.org上参与讨论,你们的热情让我激动不已。然而,连续创作技术性、趣味性兼顾的文章,压力实在不小。此外,我还有自己的工作与学习,虽然想一直和朋友们共同进步,然而力有不逮,实在是遗憾得很。总之,多谢关心咖啡馆的朋友们这几个月来一直的关心,希望机缘巧合,我们还会再会!
相关推荐
宠物咖啡馆-宠物咖啡馆平台-宠物咖啡馆平台源码-宠物咖啡馆平台java代码-宠物咖啡馆平台设计与实现-基于springboot的宠物咖啡馆平台-基于Web的宠物咖啡馆平台设计与实现-宠物咖啡馆网站-宠物咖啡馆网站源码-宠物咖啡...
宠物咖啡馆-宠物咖啡馆平台-宠物咖啡馆平台源码-宠物咖啡馆平台java代码-宠物咖啡馆平台设计与实现-基于springboot的宠物咖啡馆平台-基于Web的宠物咖啡馆平台设计与实现-宠物咖啡馆网站-宠物咖啡馆网站源码-宠物咖啡...
3. **移动文件**:解压后,你会得到一个名为 "java-8-openjdk-amd64" 的目录。为了方便使用,可以将其移动到 `/usr/lib/jvm` 目录下,这通常是存放Java版本的地方: ``` sudo mv java-8-openjdk-amd64 /usr/lib/...
总的来说,"eclipse-java-2023-09-R-linux-gtk-x86-64.tar.gz"是一个针对64位Linux系统的Eclipse IDE版本,专为Java开发者设计,提供了一整套的开发工具和服务,旨在提高开发效率和代码质量。通过解压和安装,用户...
"mysql-connector-java-5.1.7-bin.jar" 文件就是这个桥梁,它是一个Java归档(JAR)文件,包含了MySQL JDBC驱动的所有必要组件。 MySQL JDBC驱动,也被称为MySQL Connector/J,允许Java应用程序通过遵循JDBC API来...
`java-unrar-0.3.jar`是一个库,它允许Java开发者处理RAR文件,无需依赖外部命令行工具,如WinRAR。这个库为Java提供了一个简单易用的API,可以方便地实现RAR文件的解压功能。 `java-unrar-0.3.jar`库是由Andrei ...
在这个特定的版本——mysql-connector-java-5.1.40-bin.jar中,我们找到了这个连接器的5.1系列的一个稳定版本。 首先,让我们了解JDBC的作用。JDBC是Sun Microsystems(现为Oracle公司)为Java编程语言设计的一套...
解压缩mysql-connector-java-5.1.30.zip 将要使用的是mysql-connector-java-5.1.30-bin-g.jar和mysql-connector-java-5.1.30-bin.jar 配置 在C:\Program Files\Java目录下建立mysqlforjdbc子目录,进入该目录将...
版本号"3.5.3"表明这是CKEditor的一个较旧版本,发布于2011年。虽然它可能缺少一些较新版本中的特性,但依然被许多稳定的应用系统所采用。对于依赖这个版本的项目,升级需要考虑兼容性和测试问题。 7. **安全性...
mysql-connector-java-5.1.42-bin.jar 官网下载的驱动
SDK工具包中一共包含了2个类库,一个aliyun-java-sdk-core包,另外一个是alicom-dysms-api包
宠物咖啡馆平台的设计与实现代码-java-springboot-基于springboot的宠物咖啡馆平台项目-代码-源码-项目-系统-毕设-网站 1、技术栈:java,springboot,vue,ajax,maven,mysql,MyBatisPlus等 2、系统的实现 用户...
mysql驱动包 mysql-connector-java-5.1.13-bin.jar 方便快捷获取。。。
最新下载的 阿里云短信服务器所需jar包之一,... <artifactId>aliyun-java-sdk-core <version>3.2.2 如此引用即可,更多关于阿里云短信发送相关请参考http://blog.csdn.net/niaoer2010/article/details/78036664
"mysql-connector-java-5.1.15-bin.jar"是这个驱动程序的一个特定版本,版本号为5.1.15。 在Java编程环境中,当你需要连接到MySQL数据库时,你需要在类路径中包含这个JAR文件。JDBC驱动程序主要分为四种类型:Type ...
`java-property-utils-1.9.jar` 可能用于读取自定义的配置文件,例如,你可能希望根据不同的环境设置不同的CORS策略,这时可以将策略写入一个属性文件,然后使用`java-property-utils`来读取并设置过滤器的参数。...