傳智黑馬java基礎學習——day22(File、遞迴)

高數老師發表於2019-01-24

第22天 IO

今日內容介紹

  1. File
  2. 遞迴
  1. File
    1. IO概述

回想之前寫過的程式,資料都是在記憶體中,一旦程式執行結束,這些資料都沒有了,等下次再想使用這些資料,可是已經沒有了。那怎麼辦呢?能不能把運算完的資料都儲存下來,下次程式啟動的時候,再把這些資料讀出來繼續使用呢?其實要把資料持久化儲存,就需要把記憶體中的資料儲存到記憶體以外的其他持久化裝置(硬碟、光碟、U盤等)上。

當需要把記憶體中的資料儲存到持久化裝置上這個動作稱為輸出(寫)Output操作。

當把持久裝置上的資料讀取到記憶體中的這個動作稱為輸入(讀)Input操作。

因此我們把這種輸入和輸出動作稱為IO操作。


簡單瞭解IO是怎麼一回事之後,接下來就要進一步做系統瞭解。

在我們作業系統中,資料都儲存在檔案中,而檔案存放相應的資料夾中。那麼Java中是如何描述這些的呢?

    1. File類的出現

開啟API,搜尋File類。閱讀其描述:File檔案和目錄路徑名的抽象表示形式。即,Java中把檔案或者目錄(資料夾)都封裝成File物件。也就是說如果我們要去操作硬碟上的檔案,或者資料夾只要找到File這個類即可。那麼我們就要研究研究File這個類中都有那些功能可以操作檔案或者資料夾呢?

    1. File類的建構函式

  1. 通過構造方法建立File物件,我們進行演示:

public class FileDemo {

public static void main(String[] args) {

//File建構函式演示

String pathName = "e:\\java_code\\day22e\\hello.java";

File f1 = new File(pathName);//將Test22檔案封裝成File物件。注意;有可以封裝不存在檔案或者資料夾,變成物件。

System.out.println(f1);

 

File f2 = new File("e:\\java_code\\day22e","hello.java");

System.out.println(f2);

 

//將parent封裝成file物件。

File dir = new File("e:\\java_code\\day22e");

File f3 = new File(dir,"hello.java");

System.out.println(f3);

}

}

    1. File類的獲取

建立完了File物件之後,那麼File類中都有如下常用方法,可以獲取檔案相關資訊

  1. 方法演示如下:

public class FileMethodDemo {

public static void main(String[] args) {

//建立檔案物件

File file = new File("Test22.java");

//獲取檔案的絕對路徑,即全路徑

String absPath = file.getAbsolutePath();

//File中封裝的路徑是什麼獲取到的就是什麼。

String path = file.getPath();

//獲取檔名稱

String filename = file.getName();

//獲取檔案大小

long size = file.length();

 

System.out.println("absPath="+absPath);

System.out.println("path="+path);

System.out.println("filename="+filename);

System.out.println("size="+size);

}

}

 

    1. 檔案和資料夾的建立刪除等

經常上面介紹,我們知道可以通過File獲取到檔名稱,檔案路徑(目錄)等資訊。

接下來演示使用File類建立、刪除檔案等操作。

  1. 我們進行方法的演示

public class FileMethodDemo2 {

public static void main(String[] args) throws IOException {

// 對檔案或者檔案加進行操作。

File file = new File("e:\\file.txt");

// 建立檔案,如果檔案不存在,建立 true 如果檔案存在,則不建立 false。 如果路徑錯誤,IOException。

boolean b1 = file.createNewFile();

System.out.println("b1=" + b1);

//-----------刪除檔案操作-------注意:不去回收站。慎用------

 boolean b2 = file.delete();

 System.out.println("b2="+b2);

 

//-----------需要判斷檔案是否存在------------

 boolean b3 = file.exists();

 System.out.println("b3="+b3);

 

//-----------對目錄操作 建立,刪除,判斷------------

File dir = new File("e:\\abc");

//mkdir()建立單個目錄。//dir.mkdirs();建立多級目錄

boolean b4 = dir.mkdir();

System.out.println("b4="+b4);

//刪除目錄時,如果目錄中有內容,無法直接刪除。

boolean b5 = dir.delete();

//只有將目錄中的內容都刪除後,保證該目錄為空。這時這個目錄才可以刪除。

System.out.println("b5=" + b5);

 

//-----------判斷檔案,目錄------------

File f = new File("e:\\javahaha");// 要判斷是否是檔案還是目錄,必須先判斷存在。

// f.mkdir();//f.createNewFile();

System.out.println(f.isFile());

System.out.println(f.isDirectory());

}

}

    1. listFiles()方法介紹

檔案都存放在目錄(資料夾)中,那麼如何獲取一個目錄中的所有檔案或者目錄中的資料夾呢?那麼我們先想想,一個目錄中可能有多個檔案或者資料夾,那麼如果File中有功能獲取到一個目錄中的所有檔案和資料夾,那麼功能得到的結果要麼是陣列,要麼是集合。我們開始查閱API。

  1. 方法演示如下:

public class FileMethodDemo3 {

public static void main(String[] args) {

File dir = new File("e:\\java_code");

//獲取的是目錄下的當前的檔案以及資料夾的名稱。

String[] names = dir.list();

for(String name : names){

System.out.println(name);

}

//獲取目錄下當前檔案以及檔案物件,只要拿到了檔案物件,那麼就可以獲取其中想要的資訊

File[] files = dir.listFiles();

for(File file : files){

System.out.println(file);

}

}

}

 

注意:在獲取指定目錄下的檔案或者資料夾時必須滿足下面兩個條件

1,指定的目錄必須是存在的,

2,指定的必須是目錄。否則容易引發返回陣列為null,出現NullPointerException

    1. 檔案過濾器

通過listFiles()方法,我們可以獲取到一個目錄下的所有檔案和資料夾,但能不能對其進行過濾呢?比如我們只想要一個目錄下的指定副檔名的檔案,或者包含某些關鍵字的資料夾呢?

我們是可以先把一個目錄下的所有檔案和資料夾獲取到,並遍歷當前獲取到所有內容,遍歷過程中在進行篩選,但是這個動作有點麻煩,Java給我們提供相應的功能來解決這個問題。

查閱File類的API,在查閱時發現File類中過載的listFiles方法,並且接受指定的過濾器。

  1. 測試類

public class FileDemo2 {

public static void main(String[] args) {

//獲取副檔名為.java所有檔案

//建立File物件

File file = new File("E:\\code\\day11_code");

//獲取指定副檔名的檔案,由於要對所有檔案進行副檔名篩選,因此呼叫方法需要傳遞過濾器

File[] files = file.listFiles(new MyFileFilter());

//遍歷獲取到的所有符合條件的檔案

for (File f : files) {

System.out.println(f);

}

}

}

  1. 自定類繼承FilenameFilter過濾器介面

//定義類實現檔名稱FilenameFilter過濾器

class MyFileFilter implements FilenameFilter{

public boolean accept(File dir, String name) {

return name.endsWith(".java");

}

}

 

在查閱API時,我們發現,在listFiles(FileFilter filter) 也可以接受一個FileFilter過濾器,它和我們講的FilenameFilter有啥區別呢?

FilenameFilter過濾器中的accept方法接受兩個引數,一個當前檔案或資料夾所在的路徑,一個是當前檔案或資料夾物件的名稱。

FileFilter 過濾器中的accept方法接受一個引數,這個引數就當前檔案或資料夾物件

當我們需要過濾檔名稱時就可以使用FilenameFilter這個過濾器,當我們想對當前檔案或資料夾進行過濾,就可以使用FileFilter ,比如需要當前目錄下的所有資料夾,就可以使用FileFilter 過濾器。

  1. 測試類

public class FileDemo2 {

public static void main(String[] args) {

//獲取副檔名為.java所有檔案

//建立File物件

File file = new File("E:\\code\\day11_code");

//獲取指定目錄下的資料夾

File[] files = file.listFiles(new FileFileterByDir());

//遍歷獲取到的所有符合條件的檔案

for (File f : files) {

System.out.println(f);

}

}

}

  1. 自定義類繼承FileFilter過濾器介面

//檔案過濾器

class FileFileterByDir implements FileFilter{

public boolean accept(File pathname) {

return pathname.isDirectory();

}

}

 

  1. 遞迴
    1. 遞迴的概述

遞迴,指在當前方法內呼叫自己的這種現象

public void method(){

System.out.println(“遞迴的演示”);

//在當前方法內呼叫自己

method();

}

遞迴分為兩種,直接遞迴和間接遞迴。

直接遞迴稱為方法自身呼叫自己。間接遞迴可以A方法呼叫B方法,B方法呼叫C方法,C方法呼叫A方法。

  1. 遞迴的程式碼演示,計算1-n之間的和,使用遞迴完成

public class DiGuiDemo {

public static void main(String[] args) {

//計算1~num的和,使用遞迴完成

int n = 5;

int sum = getSum(n);

System.out.println(sum);

 

}

public static int getSum(int n) {

if(n == 1){

return 1;

}

return n + getSum(n-1);

}

}

  1. 程式碼執行流程圖解

注意:遞迴一定要有條件限定,保證遞迴能夠停止下來,否則會發生棧記憶體溢位。

在遞迴中雖然有限定條件,但是遞迴次數不能太多。否則也會發生棧記憶體溢位。

    1. 遞迴列印所有子目錄中的檔案路徑

編寫一個方法用來列印指定目錄中的檔案路徑,並進行方法的呼叫

要求:若指定的目錄有子目錄,那麼把子目錄中的檔案路徑也列印出來

步驟:

1. 指定要列印的目錄File物件

2. 呼叫getFileAll()方法

2.1 獲取指定目錄中的所有File物件

2.2 遍歷得到每一個File物件

2.3 判斷當前File 物件是否是目錄

判斷結果為true,說明為目錄,通過遞迴,再次呼叫步驟2的getFileAll()方法

判斷結果為false,說明是檔案,列印檔案的路徑

  1. 程式碼演示

public class FileDemo2 {

public static void main(String[] args) {

File file = new File("d:\\test");

getFileAll(file);

}

//獲取指定目錄以及子目錄中的所有的檔案

public static void getFileAll(File file) {

File[] files = file.listFiles();

//遍歷當前目錄下的所有檔案和資料夾

for (File f : files) {

//判斷當前遍歷到的是否為目錄

if(f.isDirectory()){

//是目錄,繼續獲取這個目錄下的所有檔案和資料夾

getFileAll(f);

}else{

//不是目錄,說明當前f就是檔案,那麼就列印出來

System.out.println(f);

}

}

}

}

 

    1. 搜尋指定目錄中的.java檔案(含子目錄)

需求:列印指定目錄即所有子目錄中的.java檔案的檔案路徑

要求:編寫一個方法用來列印指定目錄中的.java檔案路徑,並進行方法的呼叫

若指定的目錄有子目錄,那麼把子目錄中的.java檔案路徑也列印出來

步驟:

1. 指定要列印的目錄File物件

2. 呼叫getFileAll()方法,傳入要列印的目錄File物件

2.1 通過FilenameFilter過濾器獲取指定目錄中的所有.java型別的File物件

2.2 遍歷得到每一個File物件

2.3 判斷當前File 物件是否是目錄

判斷結果為true,說明為目錄,通過遞迴,再次呼叫步驟2的getFileAll()方法

判斷結果為false,說明是檔案,列印檔案的路徑

    1. 實現程式碼步驟
  1. 測試類

public class FileDemo4 {

public static void main(String[] args) {

File file = new File("d:\\test");

getFileAll(file);

}

//獲取指定目錄以及子目錄中的所有的檔案

public static void getFileAll(File file) {

File[] files = file.listFiles(MyFileFilter());

//遍歷當前目錄下的所有檔案和資料夾

for (File f : files) {

//判斷當前遍歷到的是否為目錄

if(f.isDirectory()){

//是目錄,繼續獲取這個目錄下的所有檔案和資料夾

getFileAll(f);

}else{

//不是目錄,說明當前f就是檔案,那麼就列印出來

System.out.println(f);

}

}

}

}

  1. 自定類繼承FilenameFilter過濾器介面

//定義類實現檔名稱FilenameFilter過濾器

class MyFileFilter implements FilenameFilter{

public boolean accept(File dir, String name) {

return name.endsWith(".java");

}

}

 

  1. 總結
    1. 知識點總結
  1. 遞迴: 方法定義中呼叫方法本身的現象
  2. 直接遞迴

public void methodA(){

methodA();

}

  1. 間接遞迴

public void metohdB(){

methodC();

}

public void methodC(){

methodB();

}

  1. 遞迴注意實現
  2. 要有出口,否則就是死遞迴
  3. 次數不能太多,否則就記憶體溢位

 

  1. File: 檔案和目錄路徑名的抽象表示形式
  2. 構造方法:

public File(String pathname) 通過給定的檔案或資料夾的路徑,來建立對應的File物件

public File(String parent, String child) 通過給定的父資料夾路徑,與給定的檔名稱或目錄名稱來建立對應的File物件

public File(File parent,  String child)通過給定的File物件的目錄路徑,與給定的資料夾名稱或檔名稱來建立對應的File物件

 

  1. 路徑的分類:
  2. 絕對路徑, 帶盤碟符

  E:\Workspace\day20_File\abc.txt

  1. 相對路徑, 不帶碟符

day20_File\abc.txt

  1. 注意: 當指定一個檔案路徑的時候,如果採用的是相對路徑,預設的目錄為 專案的根目錄

 

  1. 方法

public boolean createNewFile()建立檔案

  1. 返回值為true, 說明建立檔案成功
  2. 返回值為false,說明檔案已存在,建立檔案失敗

public boolean mkdir() 建立單層資料夾

  1. 建立資料夾成功,返回 true
  2. 建立資料夾失敗,返回 false

public boolean mkdirs() 建立多層資料夾

public boolean delete()

  1. 刪除此抽象路徑名錶示的檔案或目錄。
  2. 如果此路徑名錶示一個目錄,則該目錄必須為空才能刪除

public boolean isDirectory() 判斷是否為資料夾

public boolean isFile() 判斷是否為檔案

public boolean exists() 判斷File物件對應的檔案或資料夾是否存在

public String getAbsolutePath() 獲取當前File的絕對路徑

public String getName() 獲取當前File物件的檔案或資料夾名稱

public long length() 獲取當前File物件的檔案或資料夾的大小(位元組)

public File[] listFiles() 獲取File所代表目錄中所有檔案或資料夾的絕對路徑

相關文章