Java從入門到高級(第四天)


全球疫情不斷嚴重的時期

我的Java學習並沒有落下

好幾天沒更新有點不適應

今天我們繼續學習,繼續加油!


目錄

1. File類

1.1 獲取功能的方法

1.2 絕對路徑和相對路徑

1.3 判斷功能的方法

1.4 創建刪除功能的方法

1.5 目錄的遍歷

1.6 文件或者文件夾的判斷

2. 遞歸

2.1 遞歸實現的舉例

2.2 搜素.java文件

3. I/O

3.1 IO的分類

4. 字節流

4.1 OutputStream字節輸出流

4.2 FileOutputStream類

4.3 InputStream字節輸入流

4.4 FileInputStream類

5. 字符流

5.1 Reader字符輸入流

5.2 FileReader類

5.3 Writer字符輸出流

5.4 FileWriter類

6. IO異常的處理

7. 屬性集

7.1 Properties類


1. File類

 java.io.File 類是文件和目錄路徑名的抽象表示,主要用於文件和目錄的創建、查找和刪除等操作。

構造方法:

  •  public File(String pathname) :通過將給定的路徑名字符串轉換爲抽象路徑名來創建新的 File 實例。

  •  public File(String parent, String child) :從父路徑名字符串和子路徑名字符串創建新的 File 實例。

  •  public File(File parent, String child) :從父抽象路徑名和子路徑名字符串創建新的 File 實例。


1.1 獲取功能的方法

  •  public String getAbsolutePath() :返回此 File 的絕對路徑名字符串。

  •  public String getPath() :將此 File 轉換爲路徑名字符串。

  •  public String getName() :返回由此 File 表示的文件或目錄的名稱。

  •  public long length() :返回由此 File 表示的文件的長度。


1.2 絕對路徑和相對路徑

  • 絕對路徑:從盤符開始的路徑,這是一個完整的路徑。

  • 相對路徑:相對於項目目錄的路徑,這是一個便捷的路徑,開發中經常使用相對路徑。


1.3 判斷功能的方法

  •  public boolean exists() :此 File 表示的文件或目錄是否實際存在。

  •  public boolean isDirectory() :此 File 表示的是否爲目錄。

  •  public boolean isFile() :此 File 表示的是否爲文件。


1.4 創建刪除功能的方法

  •  public boolean createNewFile() :當且僅當具有該名稱的文件尚不存在時,創建一個新的空文件。

  •  public boolean delete() :刪除由此 File 表示的文件或目錄。

  •  public boolean mkdir() :創建由此 File 表示的目錄。

  •  public boolean mkdirs() :創建由此 File 表示的目錄,包括任何必需但不存在的父目錄。


1.5 目錄的遍歷

  •  public String[] list() :返回一個 String 數組,表示該 File 目錄中的所有子文件或目錄。

  •  public File[] listFiles() :返回一個 File 數組,表示該 File 目錄中的所有的子文件或目錄。

代碼實現:獲取當前目錄下的文件以及文件夾的名稱。

public class FileFor {
    public static void main(String[] args) {
        File dir = new File("d:\\java_projects");
      
      	// 獲取當前目錄下文件以及文件夾的名稱
	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.6 文件或者文件夾的判斷

判斷 File 對象是否是文件,是文件則輸出:xxx是一個文件,否則輸出:xxx不是一個文件。判斷 File 對象是否是文件夾,是文件夾則輸出:xxx是一個文件夾,否則輸出:xxx不是一個文件夾。

代碼實現:文件或者文件夾的判斷。

public class Test01 {
	public static void main(String[] args) {
		// 創建文件對象
		File f1 = new File("d:\\a.txt");
		
                // 判斷是否是一個文件
		if(f1.isFile()) {
			System.out.println(f1.getName()+"是一個文件");
		}  else {
			System.out.println(f1.getName()+"不是一個文件");
		}
		
                // 創建文件對象
		File f2 = new File("d:\\aa");
		
                // 判斷是否是一個文件夾
		if(f2.isDirectory()) {
			System.out.println(f2.getName()+"是一個文件夾");
		}  else {
			System.out.println(f2.getName()+"不是一個文件夾");
		}
	}
}

2. 遞歸

遞歸:指在當前方法內調用自己的這種現象。

遞歸的分類:

  • 遞歸分爲兩種,直接遞歸和間接遞歸。

  • 直接遞歸稱爲方法自身調用自己。

  • 間接遞歸可以A方法調用B方法,B方法調用C方法,C方法調用A方法。

注意事項

  • 遞歸一定要有條件限定,保證遞歸能夠停止下來,否則會發生棧內存溢出。

  • 在遞歸中雖然有限定條件,但是遞歸次數不能太多。否則也會發生棧內存溢出。

  • 構造方法:禁止遞歸。


2.1 遞歸實現的舉例

代碼實現:計算1 ~ n的和。

public class DiGuiDemo01 {
    public static void main(String[] args) {
	// 計算1~num的和,使用遞歸完成
	int num = 10;
      	
        // 調用求和的方法
	int sum = getSum(num);
      	System.out.println(sum);
		
    }
  	
    // 通過遞歸算法實現
    public static int getSum(int num) {
      	// num爲1時,方法返回1,
      	if(num == 1){
	    return 1;
	}

      	// num不爲1時,方法返回 num +(num-1)的累和
	return num + getSum(num-1);
    }
}

代碼實現:遞歸求階乘。

public class DiGuiDemo02 {
    // 計算n的階乘,使用遞歸完成
    public static void main(String[] args) {
        int n = 10;
      	
        // 調用求階乘的方法
        int value = getValue(n);
        System.out.println("階乘爲:"+ value);
    }

    // 通過遞歸算法實現。
    public static int getValue(int n) {
        if (n == 1) {
            return 1;
        }
      	
        // 不爲1則遞歸
        return n * getValue(n - 1);
    }
}

代碼實現:遞歸打印多級目錄。

public class DiGuiDemo03 {
    public static void main(String[] args) {
      	// 創建File對象
        File dir = new File("D:\\aaa");
      	
        // 調用打印目錄方法
        printDir(dir);
    }

    public static void printDir(File dir) {
      	// 獲取子文件和目錄
        File[] files = dir.listFiles();
      	
        // 循環打印
        for (File file : files) {
            if (file.isFile()) {
              	// 是文件,輸出文件絕對路徑
                System.out.println("文件名:"+ file.getAbsolutePath());
            } else {
              	// 是目錄,輸出目錄絕對路徑
                System.out.println("目錄:"+file.getAbsolutePath());
              	
                // 繼續遍歷,調用printDir,形成遞歸
                printDir(file);
            }
        }
    }
}

2.2 搜素.java文件

分析

  1. 目錄搜索,無法判斷多少級目錄,所以使用遞歸,遍歷所有目錄。

  2. 遍歷目錄時,獲取的子文件,通過文件名稱,判斷是否符合條件。

代碼實現:搜索 D:\aaa 目錄中的 .java 文件。

public class DiGuiDemo01 {
    public static void main(String[] args) {
        // 創建File對象
        File dir  = new File("D:\\aaa");
      	
        // 調用打印目錄方法
        printDir(dir);
    }

    public static void printDir(File dir) {
      	// 獲取子文件和目錄
        File[] files = dir.listFiles();
      	
      	// 循環打印
        for (File file : files) {
            if (file.isFile()) {
              	// 是文件,判斷文件名並輸出文件絕對路徑
                if (file.getName().endsWith(".java")) {
                    System.out.println("文件名:" + file.getAbsolutePath());
                }
            } else {
                // 是目錄,繼續遍歷
                printDir(file);
            }
        }
    }
}

改進:

  1. 接口作爲參數,需要傳遞子類對象,重寫其中方法。選擇匿名內部類方式,比較簡單。

  2.  accept 方法,參數爲 File ,表示當前 File 下所有的子文件和子目錄。保留住則返回true,過濾掉則返回false。保留規則:

    1. 要麼是 .java 文件。

    2. 要麼是目錄,用於繼續遍歷。

  3. 通過過濾器的作用, listFiles(FileFilter) 返回的數組元素中,子文件對象都是符合條件的,可以直接打印。

 java.io.FileFilter 是一個接口,是 File 的過濾器。 該接口的對象可以傳遞給 File 類的 listFiles(FileFilter) 作爲參數, 接口中只有一個方法。

 boolean accept(File pathname) :測試 pathname 是否應該包含在當前 File 目錄中,符合則返回true

代碼實現:搜索 D:\aaa 目錄中的 .java 文件。 (實現文件過濾器優化)

public class DiGuiDemo02 {
    public static void main(String[] args) {
        File dir = new File("D:\\aaa");
        printDir2(dir);
    }
  
    public static void printDir2(File dir) {
      	// 匿名內部類方式,創建過濾器子類對象
        File[] files = dir.listFiles(new FileFilter() {
            @Override
            public boolean accept(File pathname) {
                return pathname.getName().endsWith(".java") || pathname.isDirectory();
            }
        });
      	
        // 循環打印
        for (File file : files) {
            if (file.isFile()) {
                System.out.println("文件名:" + file.getAbsolutePath());
            } else {
                printDir2(file);
            }
        }
    }
}  

優化:

  FileFilter 是隻有一個方法的接口,因此可以用Lambda表達式簡寫。

代碼實現:搜索 D:\aaa 目錄中的 .java 文件。 (實現Lambda優化)

public static void printDir3(File dir) {
    // lambda的優化
    File[] files = dir.listFiles(f -> f.getName().endsWith(".java") || f.isDirectory());
  	
    // 循環打印
    for (File file : files) {
        if (file.isFile()) {
            System.out.println("文件名:" + file.getAbsolutePath());
      	} else {
        	printDir3(file);
      	}
    }
}

3. I/O

數據的傳輸,可以看做是一種數據的流動,按照流動的方向,以內存爲基準,分爲輸入 input 輸出 output ,即流向內存是輸入流,流出內存的輸出流。

Java中I/O操作主要是指使用 java.io 包下的內容,進行輸入、輸出操作。輸入也叫做讀取數據,輸出也叫做作寫出數據。


3.1 IO的分類

根據數據的流向分爲:輸入流輸出流

  • 輸入流 :把數據從其他設備上讀取到內存中的流。

  • 輸出流 :把數據從內存 中寫出到其他設備上的流。

格局數據的類型分爲:字節流字符流

  • 字節流 :以字節爲單位,讀寫數據的流。

  • 字符流 :以字符爲單位,讀寫數據的流。

  輸入流 輸出流
字節流 字節輸入流 InputStream 字節輸出流 OutputStream
字符流 字符輸入流 Reader 字符輸出流 Writer

4. 字節流

一切文件數據(文本、圖片、視頻等)在存儲時,都是以二進制數字的形式保存,都一個一個的字節,那麼傳輸時一樣如此。所以,字節流可以傳輸任意文件數據。在操作流的時候,我們要時刻明確,無論使用什麼樣的流對象,底層傳輸的始終爲二進制數據。


4.1 OutputStream字節輸出流

 java.io.OutputStream 抽象類是表示字節輸出流的所有類的超類,將指定的字節信息寫出到目的地。它定義了字節輸出流的基本共性功能方法。

  •  public void close() :關閉此輸出流並釋放與此流相關聯的任何系統資源。

  •  public void flush() :刷新此輸出流並強制任何緩衝的輸出字節被寫出。

  •  public void write(byte[] b) :將 b.length 字節從指定的字節數組寫入此輸出流。

  •  public void write(byte[] b, int off, int len) :從指定的字節數組寫入 len 字節,從偏移量 off 開始輸出到此輸出流。

  •  public abstract void write(int b) :將指定的字節輸出流。


4.2 FileOutputStream類

 OutputStream 有很多子類,我們從最簡單的一個子類開始。

 java.io.FileOutputStream 類是文件輸出流,用於將數據寫出到文件。

構造方法:

  •  public FileOutputStream(File file) :創建文件輸出流以寫入由指定的 File 對象表示的文件。

  •  public FileOutputStream(String name) :創建文件輸出流以指定的名稱寫入文件。

  •  public FileOutputStream(File file, boolean append) :創建文件輸出流以寫入由指定的 File 對象表示的文件。

  •  public FileOutputStream(String name, boolean append) :創建文件輸出流以指定的名稱寫入文件。

代碼實現:寫入字節、數據追加寫入、寫入換行

// 寫入字節舉例
public class FOSWrite {
    public static void main(String[] args) throws IOException {
        // 使用文件名稱創建流對象
        FileOutputStream fos = new FileOutputStream("fos.txt");     
      	
        // 寫入3個字節
      	fos.write(97); 
      	fos.write(98); 
      	fos.write(99); 

        // 關閉資源
        fos.close();
    }
}

// 數據追加續寫舉例
public class FOSWrite {
    public static void main(String[] args) throws IOException {
        // 使用文件名稱創建流對象
        FileOutputStream fos = new FileOutputStream("fos.txt",true);     
      	
        // 字符串轉換爲字節數組
      	byte[] b = "abcde".getBytes();
	
        // 寫出從索引2開始,2個字節。索引2是c,兩個字節,也就是cd
        fos.write(b);
      	
        // 關閉資源
        fos.close();
    }
}

// 寫出換行舉例
public class FOSWrite {
    public static void main(String[] args) throws IOException {
        // 使用文件名稱創建流對象
        FileOutputStream fos = new FileOutputStream("fos.txt");  
      	
        // 定義字節數組
      	byte[] words = {97,98,99,100,101};
      	
        // 遍歷數組
        for (int i = 0; i < words.length; i++) {
            // 寫出一個字節
            fos.write(words[i]);
            // 寫出一個換行
            fos.write("\r\n".getBytes());
        }
      	// 關閉資源
        fos.close();
    }
}

回車符 \r 和換行符 \n

  • 回車符:回到一行的開頭(return)。

  • 換行符:下一行(newline)。

系統中的換行:

  • Windows系統裏,每行結尾是 回車+換行 ,即 \r\n

  • Unix系統裏,每行結尾只有 換行 ,即 \n

  • Mac系統裏,每行結尾是 回車 ,即 \r 。從 Mac OS X開始與Linux統一。


4.3 InputStream字節輸入流

 java.io.InputStream 抽象類是表示字節輸入流的所有類的超類,可以讀取字節信息到內存中。它定義了字節輸入流的基本共性功能方法。

  •  public void close() :關閉此輸入流並釋放與此流相關聯的任何系統資源。

  •  public abstract int read() :從輸入流讀取數據的下一個字節。

  •  public int read(byte[] b) :從輸入流中讀取一些字節數,並將它們存儲到字節數組b中 。


4.4 FileInputStream類

 java.io.FileInputStream 類是文件輸入流,從文件中讀取字節。

構造方法:

  •  FileInputStream(File file) :通過打開與實際文件的連接來創建一個 FileInputStream ,該文件由文件系統中的 File 對象 file 命名。

  •  FileInputStream(String name) :通過打開與實際文件的連接來創建一個 FileInputStream ,該文件由文件系統中的路徑名 name 命名。

當你創建一個流對象時,必須傳入一個文件路徑。該路徑下,如果沒有該文件,會拋出 FileNotFoundException

代碼實現:複製圖片

public class Copy {
    public static void main(String[] args) throws IOException {
        // 創建流對象
        FileInputStream fis = new FileInputStream("D:\\test.jpg");
        
        // 指定目的地
        FileOutputStream fos = new FileOutputStream("test_copy.jpg");

        // 定義數組和長度
        byte[] b = new byte[1024];
        int len;
        
        // 循環讀取
        while ((len = fis.read(b))!=-1) {
            // 寫出數據
            fos.write(b, 0 , len);
        }

        // 關閉資源
        fos.close();
        fis.close();
    }
}

5. 字符流

當使用字節流讀取文本文件時,可能會有一個小問題。就是遇到中文字符時,可能不會顯示完整的字符,那是因爲一箇中文字符可能佔用多個字節存儲。所以Java提供一些字符流類,以字符爲單位讀寫數據,專門用於處理文本文件。


5.1 Reader字符輸入流

 java.io.Reader 抽象類是表示用於讀取字符流的所有類的超類,可以讀取字符信息到內存中。它定義了字符輸入流的基本共性功能方法。

  •  public void close() :關閉此流並釋放與此流相關聯的任何系統資源。

  •  public int read() :從輸入流讀取一個字符。

  •  public int read(char[] cbuf) :從輸入流中讀取一些字符,並將它們存儲到字符數組 cbuf 中 。


5.2 FileReader類

 java.io.FileReader 類是讀取字符文件的便利類。構造時使用系統默認的字符編碼和默認字節緩衝區。

構造方法:

  •  FileReader(File file) :創建一個新的 FileReader ,給定要讀取的 File 對象。

  •  FileReader(String fileName) :創建一個新的 FileReader ,給定要讀取的文件的名稱。

當你創建一個流對象時,必須傳入一個文件路徑。類似於 FileInputStream

代碼實現:讀取字符、字符數組

// 讀取字符數據舉例
public class FRRead {
    public static void main(String[] args) throws IOException {
      	// 使用文件名稱創建流對象
       	FileReader fr = new FileReader("read.txt");
        int b ;
        
        // 循環讀取
        while ((b = fr.read())!=-1) {
            System.out.println((char)b);
        }
	// 關閉資源
        fr.close();
    }
}

// 使用字符數組讀取
public class FRRead {
    public static void main(String[] args) throws IOException {
      	// 使用文件名稱創建流對象
       	FileReader fr = new FileReader("read.txt");
        int len ;
        
        // 定義字符數組,作爲裝字符數據的容器
        char[] cbuf = new char[2];
        
        // 循環讀取
        while ((len = fr.read(cbuf))!=-1) {
            System.out.println(new String(cbuf));
        }
	// 關閉資源
        fr.close();
    }
}

5.3 Writer字符輸出流

 java.io.Writer 抽象類是表示用於寫出字符流的所有類的超類,將指定的字符信息寫出到目的地。它定義了字節輸出流的基本共性功能方法。

  •  void write(int c) :寫入單個字符。

  •  void write(char[] cbuf) :寫入字符數組。

  •  abstract void write(char[] cbuf, int off, int len) :寫入字符數組的某一部分, off 數組的開始索引, len 寫的字符個數。

  •  void write(String str) :寫入字符串。

  •  void write(String str, int off, int len) :寫入字符串的某一部分, off 字符串的開始索引, len 寫的字符個數。

  •  void flush() :刷新該流的緩衝。

  •  void close() :關閉此流,但要先刷新它。


5.4 FileWriter類

 java.io.FileWriter 類是寫出字符到文件的便利類。構造時使用系統默認的字符編碼和默認字節緩衝區。

構造方法:

  •  FileWriter(File file) :創建一個新的 FileWriter ,給定要讀取的File對象。

  •  FileWriter(String fileName) :創建一個新的 FileWriter ,給定要讀取的文件的名稱。

當你創建一個流對象時,必須傳入一個文件路徑,類似於 FileOutputStream

代碼實現:寫出字符、寫出其他數據、續寫和換行

// 寫出字符舉例
public class FWWrite {
    public static void main(String[] args) throws IOException {
        // 使用文件名稱創建流對象
        FileWriter fw = new FileWriter("fw.txt");     
      	
        // 寫出4個字符
      	fw.write(97); 
      	fw.write('b'); 
      	fw.write('C'); 
      	fw.write(30000); 
      
        // 關閉資源
        fw.close();
    }
}

// 寫出字符數組
public class FWWrite {
    public static void main(String[] args) throws IOException {
        // 使用文件名稱創建流對象
        FileWriter fw = new FileWriter("fw.txt");     
      	
        // 字符串轉換爲字節數組
      	char[] chars = "玩家1和玩家2".toCharArray();
      
      	// 寫出字符數組
      	fw.write(chars);
        
	// 寫出從索引2開始,2個字節。
        fw.write(b,2,2);
      
      	// 關閉資源
        fos.close();
    }
}

// 續寫和換行
public class FWWrite {
    public static void main(String[] args) throws IOException {
        // 使用文件名稱創建流對象,可以續寫數據
        FileWriter fw = new FileWriter("fw.txt",true);     
      	
        // 寫出字符串
        fw.write("玩家1");
      	
        // 寫出換行
      	fw.write("\r\n");
      	
        // 寫出字符串
  	fw.write("玩家2");
      	
        // 關閉資源
        fw.close();
    }
}

6. IO異常的處理

可以使用JDK7優化後的 try-with-resource 語句,該語句確保了每個資源在語句結束時關閉。所謂的資源(resource)是指在程序完成後,必須關閉的對象。

格式:

try (創建流對象語句,如果多個,使用';'隔開) {
    // 讀寫數據
} catch (IOException e) {
    e.printStackTrace();
}

JDK9 try-with-resource 的改進,對於引入對象的方式,支持的更加簡潔。被引入的對象,同樣可以自動關閉,無需手動close。

格式:

// 被final修飾的對象
final Resource resource1 = new Resource("resource1");
// 普通對象
Resource resource2 = new Resource("resource2");

// 引入方式:直接引入
try (resource1; resource2) {
     // 使用對象
}


7. 屬性集

 java.util.Properties 繼承於 Hashtable ,來表示一個持久的屬性集。它使用鍵值結構存儲數據,每個鍵及其對應值都是一個字符串。該類也被許多Java類使用,比如獲取系統屬性時, System.getProperties 方法就是返回一個 Properties 對象。


7.1 Properties類

  •  public Properties() :創建一個空的屬性列表。

  •  public Object setProperty(String key, String value) :保存一對屬性。

  •  public String getProperty(String key) :使用此屬性列表中指定的鍵搜索屬性值。

  •  public Set<String> stringPropertyNames() :所有鍵的名稱的集合。

  •  public void load(InputStream inStream) :從字節輸入流中讀取鍵值對。


 

歡迎關注博主,歡迎互粉,一起學習!

感謝您的閱讀,不足之處歡迎指正!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章