1、应用递归算法显示一个目录下的所有文件及下一级子目录
(1)问题分析和解题思路
所谓的递归算法(Recursion Algorithm)是指一种通过重复将复杂的问题分解为同类的子问题而解决复杂问题的方法。而在编程语言中实现递归算法一般都是通过对函数(方法)的自调用。
计算机磁盘存储中的目录及子目录所形成的树状结构,在目录搜索时完全可以应用递归算法实现。因此,本问题的解题思路也就基本上很清晰了,应用递归算法对某个指定的目录进行迭代查询,如果其中还存在有子目录,则进行递归调用以获得下一级子目录中的文件及更下一级的子目录,直到不再有子目录为止。
(2)在MyEclipse开发工具中创建出一个类名称为ListFilesInOneDirectory,程序包名称为com.bluedream.javaio,并且包含有main()方法的Java程序类,ListFilesInOneDirectory程序类的创建过程参看如下示例图所示。
(3)在ListFilesInOneDirectory程序类中新增一个名称为getAllFilesListInOneDirectory方法
在该getAllFilesListInOneDirectory方法中根据所获得的文件路径名称信息创建出对应的File类的对象实例,然后根据该对象实例获得其内的所有文件列表及下一级子目录,同时识别该对象实例所代表的目录是否为最下一层级的目录,如果是最下一层级的子目录,则退出递归调用过程,否则将继续进行下一次的递归调用。
ListFilesInOneDirectory程序类中的getAllFilesListInOneDirectory方法的最终程序代码示例,请参看如下示例图所示的程序代码。
(4)在ListFilesInOneDirectory程序类中再设计一个带参数的构造方法
也就是在ListFilesInOneDirectory程序类中增加一个如下定义的构造方法:public ListFilesInOneDirectory(String targetPath),在该构造方法中主要是进行相关的数据初始化,最后再对getAllFilesListInOneDirectory方法进行调用以触发递归调用。该构造方法的最终程序代码示例请参看如下示例图所示的程序代码。
(5)编程ListFilesInOneDirectory程序类中的main()方法
在main()方法中主要是创建出ListFilesInOneDirectory程序类的对象实例,并传入待查询的目标目录路径字符串,最后获得通过递归调用而返回的目标目录内的所有文件名称列表及下一级子目录及其中的文件列表等信息。由于这些信息都保存在集合中,因此只需要对该集合进行迭代,就可以显示输出其中的各个文件名称信息项目。main()方法的最终程序代码示例请参看如下示例图所示的程序代码。
(6)执行本程序示例ListFilesInOneDirectory类的程序代码
在MyEclipse开发工具中右击源程序,在弹出的快捷菜单中选择“Run as”下拉菜单中的“Java Application”子菜单项目,将执行本示例ListFilesInOneDirectory类程序。操作过程请参看如下示例图所示。
(7)ListFilesInOneDirectory类程序的执行结果将在MyEclipse开发工具的控制台窗口中显示,参看如下示例图所示。
本示例程序将作者计算机磁盘中的D:\qycache目录内的所有文件及下一级子目录和其内的文件名称信息都逐个显示,并且与作者计算机中的目录和文件的存储实际情况完全一致。
2、完善示例程序实现目录级别的层级显示效果(树形)
(1)问题分析和解题思路
本问题的功能实现关键点在于如何根据目录的级别产生向右缩进一定数量的空格,从而形成层级的显示效果(也就是树形结构的层次效果)。为此需要修改ListFilesInOneDirectory程序类中的getAllFilesListInOneDirectory方法,为此方法再添加一个参数int gradeCounter 代表目录的级别数。从而可以根据该gradeCounter变量的值产生向右缩进的空格以最终产生出目录层级缩进的显示效果。
getAllFilesListInOneDirectory方法最终的程序代码请参看如下示例图所示的程序代码。
在本示例中对每个文件在某一行中从左至右分别显示出文件名称、文件创建日期时间、文件长度字节数,读者可以参看上面的程序代码示例。
(2)相应地修改ListFilesInOneDirectory程序类中的main()方法
由于getAllFilesListInOneDirectory方法的定义发生了改变,多了一个参数。因此,在main()方法中主要是修改对getAllFilesListInOneDirectory方法的调用语句,传递第2个参数的值。由于初始的目录的级别定义为最上层次,因此只需要将getAllFilesListInOneDirectory方法的第2个参数设置为0。main()方法最终的程序代码可以参考如下示例图所示的程序代码。
(3)再次执行功能扩展后的程序示例的程序代码
在MyEclipse开发工具中右击源程序,在弹出的快捷菜单中选择“Run as”下拉菜单中的“Java Application”子菜单项目,将执行本示例ListFilesInOneDirectory类程序。ListFilesInOneDirectory类程序的执行结果将在MyEclipse开发工具的控制台窗口中显示,参看如下示例图所示。
本示例程序仍然将作者计算机磁盘中的D:\qycache目录内的所有文件及下一级子目录和其内的文件名称信息都逐个显示,与前面的示例程序执行结果的差别之处在于每个文件名称信息在显示时根据该文件所属的目录层级向右缩进一定数量的空格,同一目录内的各个文件向右缩进的空格数相同,从产生出垂直对齐的显示效果。
所显示出的每个文件信息、目录信息及目录的层级关系都与作者计算机中的目录和文件的存储实际情况完全一致。功能扩展后的程序示例的程序代码执行的结果参看如下示例图所示。
如下示例图为作者计算机中的D:\qycache目录内的文件和下一级子目录的实际存储状态,示例程序的显示结果与实际的目录结构关系完全一致,本示例程序的功能实现是正确的。
3、实现文件拷贝功能
(1)问题分析和解题思路
相信读者对文件拷贝功能都不会感觉到陌生,但完成一次文件拷贝功能,其实从文件I/O的角度来看,涉及对文件的数据内容进行读/写两种操作方式。在java.io程序包中提供有实现文件数据输入输出功能操作的抽象基类InputStream/OutputStream类,在这两个基类中定义了实现文件内容操作的基本功能函数read()、 write()、close()等。
由于抽象基类是不能直接进行对象实例化的,因此在应用中一般都是创建出其派生类的对象实例(完成指定的特殊功能,如FileInputStream/FileOutputStream流类等)来实现文件读写。在文件读写的编程过程中主要应该注意异常处理的技术,本地文件读写编程的基本过程如下:
1)生成文件流对象(对文件读操作时应该为FileInputStream类,而文件写应该为FileOutputStream类);
2)调用FileInputStream或FileOutputStream类中的功能函数如read()、write(int b)等)读写文件内容;
3)关闭文件(close())。
(2)在Java程序中实现文件数据内容操作的一般方法
1)首先,根据所要操作的类型(读还是写)生成一个输入输出文件类的对象实例;
2)其次,调用此类的成员函数实现文件数据内容的读写;
3)最后,关闭此文件,并释放流对象所占用的缓存存储空间。
读者在进行Java I/O编程时,主要应该注意如下的几点要求:
1)异常的捕获——由于在java.io程序中几乎所有的流类和接口都声明有I/O异常,因此程序应该对这些异常加以处理。
2)流结束的判断——方法read()的返回值为-1时或者readLine()的返回值为null时,意味着文件流已经结束。
java.io程序包中的FileInputStream/FileOutputStream流类主要用于对本地文件读写(二进制格式读写并且是顺序读写,读和写要分别创建出不同的文件流对象)。
(3)在MyEclipse开发工具中创建出一个类名称为FileCopyUtil,程序包名称为com.bluedream.javaio,并且包含有main()方法的Java程序类,FileCopyUtil程序类的创建过程参看如下示例图所示。
(4)编程FileCopyUtil程序类的功能实现代码
为了提高程序的可读性,在FileCopyUtil程序类中定义了三个方法,它们分别是creatInputOutPutStream()、copyFileData()、closeInputOutPutStream()等方法。其中creatInputOutPutStream()方法主要是创建出输入/输出流对象实例,而copyFileData()方法完成文件的拷贝功能实现(读取源文件,并写入到),最后的closeInputOutPutStream()方法主要是关闭所创建的输入/输出流对象实例,并释放相关的存储空间。
(5)编程FileCopyUtil程序类中的main()方法的功能代码
在main()方法中主要是依据待拷贝的源文件名称和拷贝后的文件名称信息,通过调用creatInputOutPutStream()方法以创建出输入和输出流对象,然后再调用copyFileData()方法实现文件数据内容的拷贝,最后再通过调用closeInputOutPutStream()方法关闭输入和输出流对象实例以释放所占用的存储空间。main()方法的最终功能实现的程序代码请参看如下示例图所示的程序代码。
读者需要注意在Java程序中如何正确地实现跨平台的文件表示方式,在示例程序中的String sourceFileName="d:"+File.separator+"中文文件.doc";语句定义待拷贝的源文件路径和文件名称(d:\中文文件.doc),而String targetFileName="d:"+File.separator+"拷贝后的中文文件.doc"; 语句定义拷贝后的目标文件名称(d:\ 拷贝后的中文文件.doc)。
(6)执行本程序示例FileCopyUtil类的程序代码
在MyEclipse开发工具中右击源程序,在弹出的快捷菜单中选择“Run as”下拉菜单中的“Java Application”子菜单项目,将执行本示例FileCopyUtil类程序。操作过程请参看如下示例图所示。
程序执行后,将作者计算机磁盘中的d:\中文文件.doc文件拷贝为d:\ 拷贝后的中文文件.doc。本示例程序拷贝的结果参看如下示例图所示。目标文件“拷贝后的中文文件.doc”与原始的文件“中文文件.doc”完全一致,示例程序的拷贝功能是正确的。
当然,也本程序仅仅是作为示例,其中待拷贝的文件名称和拷贝后的目标文件名称都是在程序中设置的,完全可以由用户自行设定或者通过文件选择对话框选择。