1.File類簡介
File類位于java.io包中。它面向文件層次級別操作、查看文件,而字節流、字符流操作數據時顯然比之更底層。
學習File類包括以下幾個重點:文件路徑、文件分隔符、創建文件(目錄)、刪除文件(目錄)、查看文件內容(輸出目錄內文件)、判斷文件(是文件/目錄?存在否?可讀寫執行?)、獲取文件信息(文件名、路徑名、大小等),最后還有如何篩選所需文件。
2.創建、刪除文件/目錄
File類有四個構造方法:File(String pathname)、File(String parent,String child)、File(File parent,String child)、File(URI uri),暫不考慮最后一個。
File file1 = new File("D:\\myjava\\a.txt"); //File(String pathname)
File file2 = new File("D:\\myjava","a\\b.txt"); //File(String parent,String child)
File file3 = new File(file2,"abc"); //File(File parent,String child)
new一個File對象后,表示創建了一個File實例,不代表在文件系統中創建了實際的文件。要創建實際的文件、目錄,應該使用File類中提供的方法:
boolean createNewFile() throws IOException
:創建一個新的空文件,僅當文件不存在時才創建并返回true。static createTempFile()
:創建臨時文件。boolean mkdir()
:創建空目錄,僅當父路徑存在且待創建目錄不存在時才創建并返回true。注:不會遞歸創建父目錄。boolean mkdirs()
:和mkdir()不同的是,mkdirs()會遞歸創建所有所需要的父路徑。
例如,在d:\myjava(已存在)中創建d:\myjava\a.txt,d:\myjava\a\abc\c.txt,以下提供了一種方法。
File file0 = new File("xyz.txt"); //相對路徑,相對于system屬性中的user.dir路徑
File file1 = new File("D:\\myjava\\a.txt");
File file2 = new File("D:\\myjava","a\\abc");
File file3 = new File(file2,"c.txt");try {System.out.println(file1.createNewFile()); //try ... catch createNewFile()System.out.println(file2.mkdirs());System.out.println(file3.createNewFile());
} catch (IOException e) {e.printStackTrace();}
注意上面的雙反斜線\\
,因為Windows系統的文件分隔符為\
,而這是轉義符號,因此需要對\
自身進行轉義。Unix操作系統中的文件分隔符號為/
,但Windows也同樣能夠正確使用/
作為分隔符。
執行代碼,由于第一次創建文件,所以都返回true,但第二次執行都將返回false,因為待創建文件都已存在。如下:
λ java TestCreate
true
true
trueλ java TestCreate
false
false
false
File類只提供了一個delete()方法用來刪除文件和目錄,且刪除目錄時只能刪除空目錄。注:此為永久刪除,不進入回收站。
System.out.println(file1.delete()); //true
System.out.println(file2.delete()); //false
File file4 = new File("d:/myjava/a/abc/c.txt");
System.out.println(file4.delete()); //true
文件名和路徑相關問題
每一個File對象都有父路徑、文件名,兩者結合就是文件的絕對路徑。此外,路徑還分為相對路徑(抽象路徑)、絕對路徑。
以unix的路徑命名方式為例,絕對路徑/etc/ssh/ssh_config中/etc/ssh為dirname,即父路徑,ssh_config為basename。Windows中也差不多,如絕對路徑c:\windows\system32\drivers\etc\hosts中的dirname為c:\windows\system32\drivers\etc,basename部分為hosts。
以下是File類提供的與文件名、父路徑、路徑相關的方法。
getName()
:獲取文件名。獲取的內容是file對象中給定的抽象路徑名,即路徑的basename部分。getAbsoultePath()
:獲取絕對路徑名,即dirname/basename。getParent()
:獲取父路徑,即dirname。getPath()
:獲取文件路徑的字符串,其實調用的是toString()。可能返回相對路徑、也可能絕對路徑。見下文解釋。File getAbsoulteFile()
:獲取絕對路徑的文件對象,注意返回File。File getParentFile()
:獲取父路徑的文件對象,注意返回File。
在new File時,可以給定相對路徑(相對于user.dir),也可以給定絕對路徑。例如,下面4個new File中,除了第一個是相對路徑,其余三個都是絕對路徑。
File file0 = new File("xyz.txt"); //相對路徑,相對于system屬性中的user.dir路徑
File file1 = new File("D:\\myjava\\a.txt");
File file2 = new File("D:\\myjava","a\\abc");
File file3 = new File(file2,"c.txt");
當給定是相對路徑時,則getParent()和getParentFile()無法正確獲取到父路徑,返回NULL,且getPath()返回的將是相對路徑的文件名,即new File(PATH)給定什么PATH,就返回什么PATH。但無論如何,getAbsoultePath()總是能獲取到絕對路徑。
File file0 = new File("1.txt");
File file1 = new File("D:/myjava/a.txt");
File file2 = new File("D:/myjava","a/abc");
File file3 = new File(file2,"c.txt");
System.out.println("----------file0-----------------");
System.out.println(file0.getAbsoluteFile()); //D:\myjava\io\1.txt
System.out.println(file0.getAbsolutePath()); //D:\myjava\io\1.txt
System.out.println(file0.getName()); //1.txt
System.out.println(file0.getParent()); //null
System.out.println(file0.getParentFile()); //null
System.out.println(file0.getPath()); //1.txt
System.out.println("----------file1-----------------");
System.out.println(file1.getAbsoluteFile()); //D:\myjava\a.txt
System.out.println(file1.getAbsolutePath()); //D:\myjava\a.txt
System.out.println(file1.getName()); //a.txt
System.out.println(file1.getParent()); //D:\myjava
System.out.println(file1.getParentFile()); //D:\myjava
System.out.println(file1.getPath()); //D:\myjava\a.txt
System.out.println("----------file2-----------------");
System.out.println(file2.getAbsoluteFile()); //D:\myjava\a\abc
System.out.println(file2.getAbsolutePath()); //D:\myjava\a\abc
System.out.println(file2.getName()); //abc
System.out.println(file2.getParent()); //D:\myjava\a
System.out.println(file2.getParentFile()); //D:\myjava\a
System.out.println(file2.getPath()); //D:\myjava\a\abc
System.out.println("----------file3-----------------");
System.out.println(file3.getAbsoluteFile()); //D:\myjava\a\abc\c.txt
System.out.println(file3.getAbsolutePath()); //D:\myjava\a\abc\c.txt
System.out.println(file3.getName()); //c.txt
System.out.println(file3.getParent()); //D:\myjava\a\abc
System.out.println(file3.getParentFile()); //D:\myjava\a\abc
System.out.println(file3.getPath()); //D:\myjava\a\abc\c.txt
3. 文件判斷和文件屬性相關
new File對象時,無論這個對象是文件還是目錄,new的方式是一樣的,也就是說,從new File無法識別出這個對象是文件還是目錄,也無法確認這個對象對應的文件是否存在。此外,這個文件是否可讀、可寫、可執行等也都可以進行判斷。其實這些都算是文件的屬性信息,除了這些信息外,文件名、文件大小、最近一次修改時間等也都是文件屬性。
exists()
:File對象在文件系統中是否存在。isFile()
:File對象在文件系統中是否存在且是否為普通文件。isDirectory()
:File對象在文件系統中是否存在且是否為目錄。canRead()
:File對象是否可讀。canWrite()
:File對象是否可寫。canExecute()
:File對象是否可執行。
還有兩個獲取常見屬性的方法:
length()
:文件大小,單位字節。可用來判斷是否為空文件、空目錄。lastModified()
:最近一次修改時間,即mtime。
還可以設置讀、寫、執行、最近修改時間等屬性。
setLastModified(long time)
:time用從1970-01-01開始的毫秒數表示。setExecutable(true/false)
:對所有用戶是否可執行,參數為true或falsesetExecutable(true/false,true/false)
:第二個參數表示owneronly,為true時表示只有所有者可執行,否則表示所有用戶可執行。setWritable(true/false)
:和setExecute()一樣,也支持owneronly參數。setReadable(true/false)
:和setExecute()一樣,也支持owneronly參數。setReadOnly()
:設置只讀,設置成功返回true。
4. 列出目錄內文件
File類中沒有提供查看文件內容的方法,僅只提供了查看目錄內容的方法,也就是列出目錄內的文件列表。這些方法都只能列出當前目錄內容,不會遞歸到子目錄中去遍歷。
String[] list()
:返回一個字符串數組,元素為此目錄中文件的basename。String[] list(FilenameFilter filter)
:返回一個字符串數組,元素為滿足過濾條件的basename。File[] listFiles()
:返回一個抽象路徑名數組,元素為此目錄中文件的basename。File[] listFiles(FileFilter filter)
:返回抽象路徑名數組,元素為滿足過濾條件的basename。File[] listFiles(FilenameFilter filter)
:返回抽象路徑名數組,元素為滿足過濾條件的baesname。
因為文件列表返回的是多個值,甚至是多個File對象,因此這些方法返回值都是數組形式。之所以是數組而不是集合,是因為數組中的元素數量是不可更改的,而列出目錄中文件列表本就是列出當前時刻目錄內文件的動作,如果有增、刪元素的操作,豈非列出前是一個列表,實際列出的又是另一個列表?
首先看不帶過濾器的list()和listFiles(),關于文件篩選的方法見后文。假設D:\a目錄內的結構如下:
d:\a
|--a.sql
|--back.log
|--b
| |--e
| | |--1.txt
| | |--2.txt
| | `--3.txt
| `--f
| |--4.txt
| |--5.txt
| `--6.txt
|--c
| |--e
| | |--ace1.txt
| | |--ace2.txt
| | `--ace3.txt
| `--f
| |--4.txt
| |--5.txt
| `--6.txt
`--d|--a.java|--abc (1).txt|--abc (2).txt|--abc (3).txt|--b.java`--c.java
列出D:\a內的文件列表。
File file1 = new File("d:/a");
String[] list = file1.list();
for (String f : list) {System.out.println(f);
}
得到的結果為
a.sql
b
back.log
c
d
實際的過程是將目錄內的文件名存放到了字符串數組中,再遍歷數組。而且,得到的結果僅僅只是basename部分的文件名,不是絕對路徑。實際上,因為存儲在String[]中,完全沒辦法得到其絕對路徑。因此,更好的方式是使用listFiles()方法,因為它返回的是File數組,其內每一個元素都是File對象,可以使用getAbsolutePath()來獲取各元素的絕對路徑。
File file1 = new File("d:/a");
File[] filelist = file1.listFiles();
for (File file : filelist) {System.out.println(file.getAbsolutePath());
}
得到的結果為:
d:\a\a.sql
d:\a\b
d:\a\back.log
d:\a\c
d:\a\d
關于列出目錄,有如下幾個示例,見:java顯示目錄文件列表和刪除目錄。
示例1:列出整個目錄中的文件(遞歸)
示例2:列出整個目錄中的文件(隊列)
示例3:樹形結構顯示整個目錄中的文件(遞歸)
示例4:刪除整個目錄
5.篩選文件
File類的listFiles()支持文件篩選功能。例如File[] listFiles(FileFilter filter)
,其中FileFilter為過濾器接口,需要實現該接口來篩選文件。
常用的篩選方法是根據文件名,其實也支持其他篩選條件,如是否可讀、大小是否大于5M等。
import java.io.*;public class Filter1 {public static void main(String[] args) {File dir = new File("d:/myjava");getJavaFiles(dir);}public static void getJavaFiles(File dir) {File[] files = dir.listFiles(new NameFilter());for (File file:files) {if(file.isDirectory()) {getJavaFiles(file);} else {System.out.println(file.getAbsolutePath());}}}
}//實現FileFilter接口
class NameFilter implements FileFilter {public boolean accept(File pathname) {if(pathname.isDirectory()) { //為了支持遞歸篩選,判斷目錄return true;} else {String name = pathname.getName();return name.endsWith(".class")?true:false;//return pathname.canRead()?true:false; //根據是否可讀篩選//return pathname.length()>5242880?true:false; //根據大小篩選great than 5MB?(5*1024*1024)}}
}
注:若您覺得這篇文章還不錯請點擊右下角推薦,您的支持能激發作者更大的寫作熱情,非常感謝!