全球疫情不斷嚴重的時期
我的Java學習並沒有落下
好幾天沒更新有點不適應
今天我們繼續學習,繼續加油!
目錄
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文件
分析:
-
目錄搜索,無法判斷多少級目錄,所以使用遞歸,遍歷所有目錄。
-
遍歷目錄時,獲取的子文件,通過文件名稱,判斷是否符合條件。
代碼實現:搜索 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);
}
}
}
}
改進:
-
接口作爲參數,需要傳遞子類對象,重寫其中方法。選擇匿名內部類方式,比較簡單。
-
accept
方法,參數爲File
,表示當前File
下所有的子文件和子目錄。保留住則返回true,過濾掉則返回false。保留規則:-
要麼是
.java
文件。 -
要麼是目錄,用於繼續遍歷。
-
-
通過過濾器的作用,
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)
:從字節輸入流中讀取鍵值對。
歡迎關注博主,歡迎互粉,一起學習!
感謝您的閱讀,不足之處歡迎指正!