java 文件操作

 在我的前面幾篇文章中,我們介紹了流的概念,使用流我們可以任意讀取寫入文件中的內容,而對于文件的操作來說,更多的是對文件的存儲進行操作,創建文件再磁盤上,移動文件到指定位置上,更改文件的文件名等。這些操作更多的是和操作系統以及文件系統打交道。首先我們看File類。
 一個File類對象可以存放的是目錄,也可以是文件。實際上在java 7開始,引進了Files類,集合Path接口實現了對整個文件操作的分離,Files類操作文件,Path操作路徑。這篇文章先介紹File類。

一、File的構造方法

public File(String pathname)
public File(String parent, String child)
public File(File parent, String child)
 主要有三個構造方法,第一個構造方法允許傳入一個表示路徑的字符串,可以是絕對路徑也可以是相對路徑。內部調用文件系統類的方法為File對象中的實例域初始化。第二個構造方法允許傳入兩個字符串,由命名可以看出必然是可以拼接的,當然如果parent為空的話,自然是以child為路徑初始化參數,這就等于第一種方式了。第三種構造方法,傳入了一個File類的對象作為parent,其實在內部還是將此parent.path的路徑值拿出來,執行的是和第二種構造方法一樣的操作。

二、文件名和文件路徑操作
我們知道,File對象既可以存文件也可以存路徑,那么對他們的相關操作有如下幾種:

public String getName()
public String getPath()
public boolean isAbsolute()

public String getParent()
public File getParentFile()

public String getAbsolutePath()
public File getAbsoluteFile()

public String getCanonicalPath()
public File getCanonicalFile()
 主要有上述幾種對文件名和文件路徑的操作。getName很簡單,就是獲取該文件對象的文件名,內部是怎么實現的呢?我們看看代碼:
public String getName() {
        int index = path.lastIndexOf(separatorChar);
        if (index < prefixLength) return path.substring(prefixLength);
        return path.substring(index + 1);
    }
 separatorChar 表示路徑分隔符,在windows中,一般默認使用“\”,作為文件分隔符,Linux系統中使用“/”。prefixLength表示文件前綴名長度。(也就是最后一個路徑分隔符前面的所有字符串的長度),此處index拿到最后一個路徑分隔符的索引,截取此位置后面的字符串作為結果返回。這樣無論File對象中存放的是什么,都可以拿到它的name。
public class Test_InputOrOutput {
    public static void main(String[] args) throws IOException{

        File f = new File("C://Users/directory");
        System.out.println(f.getName());

    }
}
//即使File對象中存放的是路徑,依然返回路徑名directory
 接下來看看getPath這個方法。getPath就一條語句,返回該對象的私有成員path,這是當初調用構造方法傳入的pathName。isAbsolute方法調用文件系統類的方法判斷當前pathName是否是絕對路徑,getAbsolutePath獲取當前File對象的絕對路徑,相對于當前項目根目錄的位置來指定的。
 getParent方法返回當前文件對象的父目錄路徑。內部是這樣實現的:
    public String getParent() {
        int index = path.lastIndexOf(separatorChar);
        if (index < prefixLength) {
            if ((prefixLength > 0) && (path.length() > prefixLength))
                return path.substring(0, prefixLength);
            return null;
        }
        return path.substring(0, index);
    }
 和getName方法類似,都是首先找到默認路徑分隔符的最后一次出現的位置,然后通過一系列判斷處理了各種意外的情況,例如:
File f = new File("directory");
System.out.println(f.getParent());  //輸出:null

File f = new File("directory/");
System.out.println(f.getParent());  //輸出:null

File f = new File("a/directory");
System.out.println(f.getParent());  //輸出:a
 只有路徑正常的時候才會執行:return path.substring(0, prefixLength);,返回對應的父目錄的路徑。getParentFile方法返回父目錄對應的File對象。
public File getParentFile() {
        String p = this.getParent();
        if (p == null) return null;
        return new File(p, this.prefixLength);
    }
 從getParentFile的源代碼中,我們可以看到,它調用了getParent方法獲取父目錄路徑,但是如果該路徑是空的的話就返回null,否則根據此路徑構建一個新的File對象并返回。像下面這種情況就不能正確獲取getParentFile:
File f = new File("directory");
File parent = f.getParentFile();
System.out.println(parent.getPath());
//拋出空指針異常,說明parent為null
 對于這種情況難道就沒有辦法了嗎?其實可以組合getAbsoluteFile方法和getParentFile方法,來獲取父目錄的File對象。
File f = new File("directory");
File parent = f.getAbsoluteFile().getParentFile();
System.out.println(parent.getPath());

三、文件的信息
在我們的文件操作中,File對象中既可以存放文件有可以存放路徑信息,那我們怎么區分他們呢?其實在File中還封裝了一些判斷文件信息的方法。

public boolean canRead()
public boolean canWrite()
public boolean exists()
public boolean isDirectory()
public boolean isFile()
public boolean isHidden()
public long lastModified()  //最后一次修改的時間
 從方法的命名大家就可以看出來每個方法所代表的含義。(世界上最好的注釋就是沒有注釋,單命名就已經讓人理解其作用)

四、操作文件
最后是文件的操作,真正意義上的對文件在磁盤上的存儲方式進行操作。java中的File對象被創建出來之后,并不意味著在磁盤上已經創建了對應的文件,真正想要在磁盤上創建文件需要調用createNewFile方法。不用看實現代碼,這么底層的操作肯定調用的是文件系統類中的方法。
使用createNewFile創建文件成功返回true,失敗返回false。如果文件已經存在則不會去創建他,但是返回false。
文件的刪除主要有兩個方法。delete和deleteOnExit,前者會刪除文件或者目錄返回boolean,后者標記一下,等到虛擬機退出時候進行實際刪除操作。需要注意的是如果將要刪除的文件目錄不為空就不能完成刪除操作。

File f = new File("a");
f.mkdir();

File d = new File("a/a.txt");
d.createNewFile();

System.out.println(f.delete());
//輸出結果:false
 所以在我們將要刪除一個目錄的時候就需要清空其中的所有內容。

五、目錄操作
最后說說目錄操作,其實在我們上面的代碼中也已經稍有涉及了。創建一個目錄有兩種方法:

public boolean mkdir()
public boolean mkdirs()
 這兩個操作有一定的區別,比如我要在c盤根目錄下創建一個名為a的文件夾,new File("C://a").mkdir();或者new File("C://a").mkdirs();。浪著的效果是一樣的。但是如果我要在c盤的b文件夾中創建一個d目錄,其中b文件夾不存在。mkdir方法就無法完成任務了,因為中間有個文件夾b沒有被創建。而mkdirs會將b文件夾也一起創建了。這就是它倆的區別。
 關于目錄操作的最后一個就是目錄的遍歷。File中也提供了很多方法。
public String[] list()
public File[] listFiles()

public String[] list(FilenameFilter filter)
public File[] listFiles(FilenameFilter filter)
public File[] listFiles(FileFilter filter)
 調用list返回目錄下的所有文件的name:
File f = new File("f:/360");
String[] list = f.list();
for (String s : list){
    System.out.println(s);
}
//這是在我的f盤下的360文件夾中的所有文件名
輸出結果:
360defender
360sdSetup.exe
360zip
 毋庸置疑,listFiles返回的是這些文件名構成的File對象數組。我們重點看剩下的幾個方法,他們都傳入了一個參數,這個參數其實就是過濾器,用來對目錄下的文件進行進一步的篩選。他們兩個都是函數式接口,只有一個方法。該方法返回true表示遍歷中的當前的目錄或者文件可以作為結果返回到結果集中。
public interface FileFiter{
    boolean accept(File pathName);
}

public interface FilenameFiter{
    boolean accept(File dir,String name);
}
 針對上述介紹,演示一個實例,使用的還是我的f盤下的360文件夾。
public static void main(String[] args) throws IOException{

        File f = new File("f:/360");

        File[] s = f.listFiles(new FileFilter() {

            @Override
            public boolean accept(File pathname) {
                return pathname.isDirectory() ? true : false;
            }
        });


        for (File name : s){
            System.out.println(name.getName());
        }
    }
 上述代碼過濾篩選出,360文件夾中所有目錄的文件,輸出他們的名字。

 本篇文章結束,主要介紹了File類的一些使用情況,實際上java 7 中引進了Files類和Path接口實現了分離File類的作用,下篇文章我們一起探討,本文若有不當之處,希望指出!
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,885評論 6 541
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,312評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 177,993評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,667評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,410評論 6 411
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,778評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,775評論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,955評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,521評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,266評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,468評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,998評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,696評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,095評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,385評論 1 294
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,193評論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,431評論 2 378

推薦閱讀更多精彩內容

  • 自從java 7以來,引入了FIles類和Path接口。他們兩封裝了用戶對文件的所有可能的操作,相比于java 1...
    Single_YAM閱讀 2,581評論 2 8
  • 1. Java基礎部分 基礎部分的順序:基本語法,類相關的語法,內部類的語法,繼承相關的語法,異常的語法,線程的語...
    子非魚_t_閱讀 31,733評論 18 399
  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,823評論 18 139
  • Java 語言支持的類型分為兩類:基本類型和引用類型。整型(byte 1, short 2, int 4, lon...
    xiaogmail閱讀 1,363評論 0 10
  • 王柏林 公司: 都江堰佳音英語 【日精進打卡第59天】 【知~學習】 《六項精進》 《大學》 【名句】 逢人且說三...
    berlin_eda3閱讀 223評論 0 0