小師妹學JavaIO之:目錄仍是文件

簡介

目錄和文件傻傻分不清楚,目錄和文件的本質究竟是什麼?在java中怎麼操縱目錄,怎麼遍歷目錄。本文F師兄會爲你們一一講述。java

linux中的文件和目錄

小師妹:F師兄,我最近有一個疑惑,java代碼中好像只有文件沒有目錄呀,是否是當初發明java的大神,一不當心走了神?node

F師兄:小師妹真勇氣可嘉呀,勇於質疑權威是從小工到專家的最重要的一步。想一想F師兄我,從小沒人提點,老師講什麼我就信什麼,專家說什麼我就聽什麼:股市必上一萬點,房子是給人住的不是給人炒的,原油寶固然是小白理財必備產品....而後,就沒有而後了。linux

更多精彩內容且看:git

更多內容請訪問 www.flydean.com

雖然java中沒有目錄的概念只有File文件,而File實際上是能夠表示目錄的:程序員

public boolean isDirectory()

File中有個isDirectory方法,能夠判斷該File是不是目錄。github

File和目錄傻傻分不清楚,小師妹,有沒有聯想到點什麼?數據結構

小師妹:F師兄,我記得你上次講到Linux下面全部的資源均可以看作是文件,在linux下面文件和目錄的本質是否是同樣的?工具

對的,在linux下面文件是一等公民,全部的資源都是以文件的形式來區分的。佈局

什麼扇區,邏輯塊,頁之類的底層結構咱們就不講了。咱們先考慮一下一個文件到底應該包含哪些內容。除了文件自己的數據以外,還有不少元數據的東西,好比文件權限,全部者,group,建立時間等信息。區塊鏈

在linux系統中,這兩個部分是分開存儲的。存放數據自己的叫作block,存放元數據的叫作inode。

inode中存儲了block的地址,能夠經過inode找到文件實際數據存儲的block地址,從而進行文件訪問。考慮一下大文件可能佔用不少個block,因此一個inode中能夠存儲多個block的地址,而一個文件一般來講使用一個inode就夠了。

爲了顯示層級關係和方便文件的管理,目錄的數據文件中存放的是該目錄下的文件和文件的inode地址,從而造成了一種一環套一環,圓環套圓環的鏈式關係。

上圖列出了一個經過目錄查找其下文件的環中環佈局。

我想java中目錄沒有單獨列出來一個類的緣由多是參考了linux底層的文件佈局吧。

目錄的基本操做

由於在java中目錄和文件是公用File這個類的,因此File的基本操做目錄它全都會。

基本上,目錄和文件相比要多注意下面三類方法:

public boolean isDirectory()
public File[] listFiles() 
public boolean mkdir()

爲何說是三類呢?由於還有幾個和他們比較接近的方法,這裏就不一一列舉了。

isDirectory判斷該文件是否是目錄。listFiles列出該目錄下面的全部文件。mkdir建立一個文件目錄。

小師妹:F師兄,以前咱們還以目錄的遍歷要耗費比較長的時間,通過你一講解目錄的數據結構,感受listFiles並非一個耗時操做呀,全部的數據都已經準備好了,直接讀取出來就行。

對,看問題不要看表面,要看到隱藏在表面的本質內涵。你看師兄我平時不顯山露水,實際上是真正的中流砥柱,堪稱公司優秀員工模範。

小師妹:F師兄,那平時也沒看上頭表彰你啥的?哦,我懂了,必定是老闆怕表彰了你引發別人的嫉妒,會讓你的好好大師兄的形象崩塌吧,看來老闆真的懂你呀。

目錄的進階操做

好了小師妹,你懂了就行,下面F師兄給你講一下目錄的進階操做,好比咱們怎麼拷貝一個目錄呀?

小師妹,拷貝目錄簡單的F師兄,上次你就教我了:

cp -rf

一個命令的事情不就解決了嗎?難道里面還隱藏了點祕密?

咳咳咳,祕密卻是沒有,小師妹,我記得你上次說要對java從一而終的,今天師兄給你介紹一個在java中拷貝文件目錄的方法。

其實Files工具類裏已經爲咱們提供了一個拷貝文件的優秀方法:

public static Path copy(Path source, Path target, CopyOption... options)

使用這個方法,咱們就能夠進行文件的拷貝了。

若是想要拷貝目錄,就遍歷目錄中的文件,循環調用這個copy方法就夠了。

小師妹:且慢,F師兄,若是目錄下面還有目錄的,目錄下還套目錄的狀況該怎麼處理?

這就是圈套呀,看我用個遞歸的方法解決它:

public void useCopyFolder() throws IOException {
        File sourceFolder = new File("src/main/resources/flydean-source");
        File destinationFolder = new File("src/main/resources/flydean-dest");
        copyFolder(sourceFolder, destinationFolder);
    }

    private static void copyFolder(File sourceFolder, File destinationFolder) throws IOException
    {
        //若是是dir則遞歸遍歷建立dir,若是是文件則直接拷貝
        if (sourceFolder.isDirectory())
        {
            //查看目標dir是否存在
            if (!destinationFolder.exists())
            {
                destinationFolder.mkdir();
                log.info("目標dir已經建立: {}",destinationFolder);
            }
            for (String file : sourceFolder.list())
            {
                File srcFile = new File(sourceFolder, file);
                File destFile = new File(destinationFolder, file);
                copyFolder(srcFile, destFile);
            }
        }
        else
        {
            //使用Files.copy來拷貝具體的文件
            Files.copy(sourceFolder.toPath(), destinationFolder.toPath(), StandardCopyOption.REPLACE_EXISTING);
            log.info("拷貝目標文件: {}",destinationFolder);
        }
    }

基本思想就是遇到目錄我就遍歷,遇到文件我就拷貝。

目錄的腰疼操做

小師妹:F師兄,假如我想刪除一個目錄中的文件,或者咱們想統計一下這個目錄下面到底有多少個文件該怎麼作呢?

雖然這些操做有點腰疼,仍是能夠解決的,Files工具類中有個方法叫作walk,返回一個Stream對象,咱們可使用Stream的API來對文件進行處理。

刪除文件:

public void useFileWalkToDelete() throws IOException {
        Path dir = Paths.get("src/main/resources/flydean");
        Files.walk(dir)
                .sorted(Comparator.reverseOrder())
                .map(Path::toFile)
                .forEach(File::delete);
    }

統計文件:

public void useFileWalkToSumSize() throws IOException {

        Path folder = Paths.get("src/test/resources");
        long size = Files.walk(folder)
                .filter(p -> p.toFile().isFile())
                .mapToLong(p -> p.toFile().length())
                .sum();
        log.info("dir size is: {}",size);
    }

總結

本文介紹了目錄的一些很是常見和有用的操做。

本文的例子https://github.com/ddean2009/learn-java-io-nio

本文做者:flydean程序那些事

本文連接:http://www.flydean.com/java-io-directory/

本文來源:flydean的博客

歡迎關注個人公衆號:程序那些事,更多精彩等着您!

相關文章
相關標籤/搜索