在上一章,我們理清了有哪些該清理的文件,事實上,還有很多文件是可以清理的,如下是百度搜索"垃圾文件給出的定義":
在Windows操作系統(tǒng)安裝和使用過程中都會產(chǎn)生相當多的垃圾文件,
包括臨時文件(如:*.tmp瓤摧、*._mp)日志文件(*.log)摇零、
臨時幫助文件(*.gid)、磁盤檢查文件(*.chk)、
臨時備份文件(如:*.old、*.bak)以及其他臨時文件。
特別是如果一段時間不清理IE的臨時文件夾“Temporary Internet Files”席揽,其中的緩存文件有時會占用上百MB的磁盤空間。
這些垃圾文件不僅僅浪費了寶貴的磁盤空間谓厘,嚴重時還會使系統(tǒng)運行慢如蝸牛幌羞。
這點相信你肯定忍受不了吧!所以應及時清理系統(tǒng)的垃圾文件的淤塞竟稳,保持系統(tǒng)的“苗條”身材属桦,輕松流暢上網(wǎng)!
關于其他可清理文件類型日后再談,在這一章我們主要要了解的是,怎么清理?
方案一:寫個批量操作的bat文件,然后雙擊食用.(正如百度百科詞條下那個例子)
方案二:使用一門熱門的編程語言編寫一個含有GUI操作和眾多自定義條目的桌面應用程序.
當然了,我們毫無理由再做方案一這種重復而且沒有挑戰(zhàn)的事情.
那么既然我們選擇了方案二,那么就用JAVA編寫清理內(nèi)核,JAVAFX編寫GUI吧!
筆者決定從處理垃圾文件的內(nèi)核開始從內(nèi)向外的編寫,所以現(xiàn)在我們需要完成的功能是編寫清理器類,稍微思考構思下,可以想到我們未來的內(nèi)核可能是這樣分布的:
Reader類負責讀取文件結(jié)構,
SuffixFilter類負責篩選所需要的特定文件類型,
Cleaner類負責遍歷文件結(jié)構清理.
先編寫Reader,思路是使用listFile方法,遍歷文件,然后進行迭代來深度遍歷找出所有文件出來.
/**
* 得到過濾器下的淺度搜索目標文件下的所有文件
*
* @param path
* 文件地址字符串
*
* @return 正常文件夾返回文件列表,空文件夾和文件返回空數(shù)組,地址不存在返回空
*/
public File[] getFiles(String path) {
File file = new File(path);
if (file.exists()) {
if (file.isFile()) {
return new File[0];
}
else {
return file.listFiles();
}
}
else {
return null;
}
}
/**
* 得到過濾器下的深度搜索目標文件下的所有文件
*
* @param path
* 文件地址字符串
*
* @return 一個存放所有文件集合的HashMap
*/
public HashMap<File, File[]> getAllFiles(String path) {
File[] files = getFiles(path);
this.fileMap.put(new File(path), files);
// 如果路徑不存在或者是空文件夾或文件,則跳出遞歸
if (files != null && files.length != 0) {
for (File file : files) {
getAllFiles(file.getPath());
}
}
return this.fileMap;
}
這里筆者使用了HashMap存儲文件結(jié)構.它能讓我清晰的知道哪個文件夾對應的哪些子文件,其中父文件是key,然后子文件們的數(shù)組是value.
以上代碼基本就是Reader類的核心,現(xiàn)在我們要思索下我們這個Reader類應該具備哪些屬性,也就是說,我們需要的哪些數(shù)據(jù)是應該存儲到Reader類的?這直接影響了構造函數(shù)和字段.
首先是文件結(jié)構HashMap要當做這個類的字段的,這也是這個類存在的原因之一.另外,Reader也不是瞎Read,起碼得知道我需要從哪讀取,讀取什么?
事實上,這是兩個問題,首先是從哪讀取,我們大可用字符串來構造這個"哪"字,比如C盤:"C:/".然后是讀取什么,這也很關鍵,我們需要清理的是一個垃圾文件的集合,如果所有的文件全部讀取出來然后清除大概又要參考我的第一篇文章重裝系統(tǒng)了喲.
所以說,我們需要一個過濾器,來過濾出真正的垃圾文件.很幸運,java自己就有這么一個過濾器類:Filter.Filter類里面只有一個方法accept,這個方法返回值是布爾,true代表著通過了過濾,false代表著沒有通過,我們重寫這個方法就可以指定哪些需要過濾哪些不需要了.
這時候我們需要這個SuffixFilter類了.我們利用這個類繼承Filter然后重寫它的方法:
package coreCleaner;
import java.io.*;
/**
* @author jinshuguangze
* @version 1.1
*/
public class SuffixFilter implements FilenameFilter {
// 過濾器集,一般以文件類型作為區(qū)分,比如{".exe"}就是過濾出應用程序的
private String[] suffix;
/**
* 構造函數(shù)
*
* @param suffix
* 過濾字符串數(shù)組
*/
public SuffixFilter(String[] suffix) {
this.suffix = suffix;
}
/**
* 重寫的過濾方法,使用或運算符號得出是否通過
*
* @param dir
* 要過濾的文件
* @param name
* 文件名
* @return 如果通過過濾就是true,沒有通過就是false
*/
@Override
public boolean accept(File dir, String name) {
boolean pass = false;
for (int i = 0; i < suffix.length; i++) {
pass = pass || name.endsWith(suffix[i]);
}
return pass;
}
}
這里面利用了或運算來篩選多個過濾器.
我們其實大可不必專門為它寫個類的,直接使用匿名內(nèi)部類來解決會更方便,不過筆者考慮到程序進一步擴展可能需要指定不同的過濾方案,所以還是把它單獨寫成一個類了.
有了過濾器,我們就能寫一個過濾之前的文件結(jié)構產(chǎn)生新文件結(jié)構的方法了.
/**
* 得到過濾器下的文件文件結(jié)構
*
* @param fileMap
* 文件結(jié)構
* @return 過濾后的文件結(jié)構
*/
public HashMap<File, File[]> getFilterFiles(HashMap<File, File[]> fileMap) {
// 防止一開始給予的路徑就是不存在路徑
if (fileMap == null) {
return null;
}
fileMap.forEach((k, v) -> {
// 防止子目錄有不存在路徑
if (v != null) {
Vector<File> acceptFile = new Vector<>();
SuffixFilter filter = new SuffixFilter(suffix);
for (File file : v) {
if (filter.accept(file.getParentFile(), file.getName())) {
acceptFile.add(file);
}
}
// 如果沒有文件滿足過濾器,那么put進去的是個空數(shù)組
this.fileMapFilter.put(k, acceptFile.toArray(new File[acceptFile.size()]));
}
});
return this.fileMapFilter;
}
PS:可能其中的filter.accept()會看上去比較愚蠢,因為可以直接利用邏輯關系寫個方法就行了而不用專門寫個類,不過筆者還是堅信在發(fā)展中,需求會越來越膨脹的,而且file.listFiles()方法里面可以直接加這個Filter參數(shù),效果會很好:\
這時候我們很明確的知道我們需要的字段有:需要從哪處理的根目錄,過濾器,根目錄下所有文件集,過濾器下所有文件集.(事實上能從上面的代碼中看出來,這是因為筆者提前寫好代碼的原因,如果不知道這點的話還是得花點時間來思索考量的)
這時我們的Reader類基本只差一些零零散散的setter,getter了.值得注意的是,關于setter筆者只開放了過濾器的setter,代碼是這樣的:
/**
* 設置過濾器
*
* @param suffix
*/
public void setSuffix(String... suffix) {
this.suffix = suffix;
getFilterFiles(this.fileMap);
}
這是由于文件結(jié)構讀取出來了,可以快速的更換過濾器來求出它的子集,而開放其余幾個字段是毫無意義的.
值得一提的是,在構造器方面,為了保證這個類每次構造出新的對象就直接讀取,可以直接在構造器中加方法:
/**
* 構造函數(shù)
*
* @param rootPath
* 根文件地址字符串
* @param suffix
* 過濾字符串數(shù)組
*/
public Reader(String rootPath, String... suffix) {
this.rootPath = rootPath;
this.suffix = suffix;
getFilterFiles(getAllFiles(rootPath));
}
這個文章過后我們基本把過濾器類和讀取類寫完了,下篇文章我們討論清除類和其他一些類的思路.