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);
}
}
}