1. 程式人生 > >Java SE 高階開發之Java IO 之 File(檔案操作)

Java SE 高階開發之Java IO 之 File(檔案操作)

File檔案操作類

在Java.io包之中,File類是唯一一個與檔案本身操作(建立、刪除、取得資訊..)有關的程式類。

File類的基本使用
java.io.File類是一個普通的類,直接產生例項化物件即可。如果要例項化物件則需要使用到兩個構造方法:

public File(String pathname) ;
public File(String parent, String child);//設定父路徑和子路徑。

如果要想進行檔案的基本操作,可以使用File類的如下方法:

建立一個新檔案 :
public boolean createNewFile() throws IOException

例:在指定路徑下建立新檔案

public class Test {
    public static void main(String[] args) {
        //定義要操作的檔案路徑
        File file = new File("C:\\Users\\貴軍\\Desktop\\testIO.java");
        try {
            file.createNewFile();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

File類只是建立檔案本身,但是對於其內容並不做處理。
其他一些常用方法

判斷檔案是否存在:
public boolean exists()
刪除檔案:
public boolean delete()

例:編寫檔案的基本操作(如果檔案不存在則進行建立;存在則刪除)

public class Test {
    public static void main(String[] args) {
        //定義要操作的檔案路徑
        File file = new File("C:\\Users\\貴軍\\Desktop\\testIO.java");
        if
(file.exists()) { //如果檔案存在 file.delete(); //則刪除 } else { //檔案不存在 try { file.createNewFile(); //則進行建立 } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }

以上實現了最簡化的檔案處理操作,但是程式碼存在兩個問題:

實際專案部署環境可能與開發環境不同。那麼這個時候路徑的問題就很麻煩了。windows下使用的是”\”,而Unix系統下使用的是”/”。所以在使用路徑分隔符時都會採用File類的一個常量”public static final String separator “來描述。

separator由不同作業系統下的JVM來決定到底是哪個槓槓!
因此以上指定檔案路徑的語句就可以改寫為

//定義要操作的檔案路徑
        File file = new File(
                "C:"+File.separator+"Users"+File.separator+"貴軍"+
        File.separator+"Desktop"+File.separator+"testIO.java");

注意:在Java中要進行檔案的處理操作是要通過本地作業系統支援的,在這之中如果操作的是同名檔案,就可能出現延遲的問題。(開發之中儘可能避免檔案重名問題)

目錄操作

File類中關於目錄有如下方法:

取得父路徑或父File物件:
public String getParent()
public File getParentFile()

若想建立父路徑,此時最好取得父路徑的File類物件。

建立目錄(無論有多少級父目錄,都會建立)
public boolean mkdirs()

例:Java檔案目錄操作

public class Test {
    public static void main(String[] args) {
        //separator由不同的作業系統下的JVM來決定到底是哪個槓槓!!!
        File file = new File("C:"+File.separator+"Users"+File.separator+"貴軍"+
        File.separator+"Desktop"
                +File.separator+"JavaIO"+File.separator+"bit"+File.separator+"testIO.java");
        if(!file.getParentFile().exists()) {        //如果檔案testIO.java的父目錄不存在
            file.getParentFile().mkdirs();          //則有多少級父目錄就建立多少級父目錄
        }
        if(file.exists()) {                         //如果檔案存在
            file.delete();                          //則進行刪除
        } else {                                    //否則
            try {
                file.createNewFile();               //進行建立檔案
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}

取得檔案資訊
在File類裡面提供有一系列取得檔案資訊的操作:

判斷路徑是否是檔案: public boolean isFile();
判斷路徑是否是目錄: public boolean isDirectory();
取得檔案大小(位元組): public long length();
最後一次修改日期 : public long lastModified();

例:取得檔案資訊

public class Test {
    public static void main(String[] args) {
        //要操作的檔案
        File file = new File("C:"+File.separator+"Users"+File.separator+"貴軍"+
                File.separator+"Desktop"+File.separator+"test.png");
        //上面給定的父目錄都存在,如果不存在則需要先建立父路徑
        if(file.exists() && file.isFile()) {        //如果檔案存在再進行操作
            System.out.println("檔案大小: " + file.length());
            System.out.println("最後一次修改檔案的日期: " + new Date(file.lastModified()));
        } else {                                    //如果檔案不存在時
            try {
                System.out.println("檔案不存在則先進行建立");
                file.createNewFile();               //先進行檔案建立
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            if(file.exists() && file.isFile()) {    //再一次確定檔案存在了再進行操作
                System.out.println("檔案大小: " + file.length());
                System.out.println("最後一次修改檔案的日期: " + new Date(file.lastModified()));
            }
        }
    }
}

執行結果
這裡寫圖片描述
以上操作都是針對檔案進行資訊取得,Java裡也提供有如下方法列出一個目錄的全部組成:

public File[] listFiles();

例:列出目錄中的全部組成

public class Test {
    public static void main(String[] args) {
        //要操作的檔案
        File file = new File("C:"+File.separator+"Users"+File.separator+"貴軍"+
                File.separator+"Desktop");
        if(file.exists() && file.isDirectory()) {
            //列出目錄中的全部內容
            File[] files = file.listFiles();
            for(File i : files) {
                System.out.println(i);
            }
        }
    }
}

這裡寫圖片描述

綜合案例(目錄列表)
雖然File提供有listFiles()方法,但是這個方法本身只能夠列出本目錄中的第一級資訊。如果要求列出目錄中所有級的資訊,必須自己來處理。這種操作就必須通過遞迴的模式來完成。
例:遞迴列印當前目錄下所有層級的檔案資訊

public class Test {
    public static void main(String[] args) {
        //指定路徑
        File file = new File("C:"+File.separator+"Users"+File.separator+"貴軍"+
                File.separator+"Desktop"+File.separator+"JavaIO");
        listAllFiles(file);
    }
    public static void listAllFiles(File file) {
        if(file.isDirectory()) {                    //判斷是目錄就繼續進入
            File[] files = file.listFiles();        //繼續列出子目錄
            for(int i = 0; i < files.length; i++) { //對每個子目錄都進行遞迴
                listAllFiles(files[i]);
            }
        } else {                                    //是檔案就直接列印
            System.out.println(file);
        }
    }
}

執行緒阻塞問題:
現在所有程式碼都是在main執行緒下完成的,如果listAllFiles()方法沒有完成,那麼對於main後續的執行將無法完成。這種耗時的操作讓主執行緒出現了阻塞,而導致後續程式碼無法正常執行完畢。如果不想讓阻塞產生,最好再產生一個新的執行緒進行處理。

例:新增子執行緒進行耗時操作

public class Test {
    public static void main(String[] args) {
        //開啟子執行緒進行處理
        new Thread(()-> {
            File file = new File("C:"+File.separator+"Users"+File.separator+"貴軍"+
                File.separator+"Desktop"+File.separator+"JavaIO");
            listAllFiles(file);
        }).start();
        System.out.println("開始進行檔案輸出");
    }
    public static void listAllFiles(File file) {
        if(file.isDirectory()) {                    //判斷是目錄就繼續進入
            File[] files = file.listFiles();        //繼續列出子目錄
            for(int i = 0; i < files.length; i++) { //對每個子目錄都進行遞迴
                listAllFiles(files[i]);
            }
        } else {                                    //是檔案就直接列印
            System.out.println(file);
        }
    }
}