文章目錄
- Java 文件操作
- 構造方法
- 文件屬性操作
- 文件內容操作
- InputStream
- Reader
- OutputStream
- Writer
- 更多案例
- 文件查找
- 普通文件的復制
Java 文件操作
Java 中通過 java.io.File
類來對文件進行描述。
構造方法
構造方法 | 說明 |
---|---|
File(String pathname) | 通過路徑名字符串來創建 File 實例 |
File(String parent, String child) | 從父路徑名字符串和子路徑名字符串創建 File 實例 |
File(File parent, String child) | 從父抽象路徑名和子路徑名字符串創建 File 實例 |
注意:創建 File 實例不等于創建文件
文件屬性操作
方法 | 說明 |
---|---|
String getParent() | 返回父路徑名字符串 |
String getName() | 返回該抽象路徑名表示的文件或目錄的名稱 |
String getPath() | 將此抽象路徑名轉換為路徑名字符串 |
String getAbsolutePath() | 返回此抽象路徑名的絕對路徑名字符串 |
String getCanonicalPath() | 返回此抽象路徑名的規范路徑名字符串 |
boolean exists() | 測試此抽象路徑名表示的文件或目錄是否存在 |
boolean isDirectory() | 測試此抽象路徑名表示的文件是否為目錄 |
boolean isFile() | 測試此抽象路徑名表示的文件是否為普通文件 |
boolean createNewFile() | 當且僅當具有此名稱的文件還不存在時,原子地創建一個由該抽象路徑名命名的新的空文件。 |
boolean delete() | 刪除由該抽象路徑名表示的文件或目錄 |
void deleteOnExit() | 請求在虛擬機終止時刪除由該抽象路徑名表示的文件或目錄 |
String[] list() | 返回該抽象路徑名下的文件名 |
File[] listFiles() | 返回一個抽象路徑名數組,表示該抽象路徑名所表示的目錄中的文件 |
boolean mkdir() | 創建以此抽象路徑名命名的目錄 |
boolean mkdirs() | 創建以此抽象路徑名命名的目錄,如果必要,會創建中間目錄 |
boolean renameTo(File dest) | 重命名由該抽象路徑名表示的文件 |
boolean canRead() | 測試應用程序是否可以讀取由該抽象路徑名表示的文件 |
boolean canWrite() | 測試應用程序是否可以修改由該抽象路徑名表示的文件 |
示例:
public static void main(String[] args) throws IOException {File file = new File("d:/test.txt");System.out.println(file.getParent()); // d:\System.out.println(file.getName()); // test.txtSystem.out.println(file.getPath()); // d:\test.txtSystem.out.println(file.getAbsolutePath()); // d:\test.txtSystem.out.println(file.getCanonicalPath()); // D:\test.txt
}
public static void main(String[] args) throws IOException {File file = new File("helloworld.txt");System.out.println(file.exists()); // falseSystem.out.println(file.isDirectory()); // falseSystem.out.println(file.isFile()); // falseSystem.out.println("=============================");// 創建文件file.createNewFile();System.out.println(file.exists()); // trueSystem.out.println(file.isDirectory()); // falseSystem.out.println(file.isFile()); // true
}
public static void main(String[] args) {File file = new File("helloworld.txt");// 刪除文件file.delete();System.out.println(file.exists()); // false
}
public static void main(String[] args) throws IOException, InterruptedException {File file = new File("helloworld.txt");// 把文件創建回來file.createNewFile();// 在程序退出前刪除file.deleteOnExit();Thread.sleep(5000);System.out.println(file.exists()); // true
}
public static void main(String[] args) {// 創建目錄File file = new File("test");System.out.println(file.exists()); // falseSystem.out.println(file.isDirectory()); // falseSystem.out.println("========================");file.mkdir();System.out.println(file.exists()); // trueSystem.out.println(file.isDirectory()); // true
}
public static void main(String[] args) {// 創建多級目錄File file = new File("test/a/b/c");System.out.println(file.exists()); // falseSystem.out.println(file.isDirectory()); // falseSystem.out.println("========================");file.mkdirs();System.out.println(file.exists()); // trueSystem.out.println(file.isDirectory()); // true
}
public static void main(String[] args) throws IOException {// 文件重命名File file1 = new File("test1.txt");File file2 = new File("test2.txt");file1.createNewFile(); // 創建 test1.txtfile1.renameTo(file2); // 重命名成 test2.txt
}
文件內容操作
相關的類:
- 字節流:
InputStream
OutputStream
,用于操作二進制文件 - 字符流:
Reader
Writer
,用于操作文本文件
InputStream
方法 | 說明 |
---|---|
int read() | 從輸入流中讀取下一個字節的數據。值字節以 int 形式返回,其范圍為 0 到 255。如果由于到達流的末尾而沒有可用的字節,則返回值 -1。此方法會阻塞,直到輸入數據可用、檢測到流的末尾或引發異常為止。 |
int read(byte b[]) | 從輸入流中讀取一定數量的字節,并將其存儲到數組 b 中,并且盡可能把 b 填滿。實際讀取的字節數以整數形式返回。此方法會阻塞,直到輸入數據可用、檢測到文件結尾或引發異常為止。 |
int read(byte b[], int off, int len) | 也是把讀到的字節往 b 里塞,從 off 的位置開始塞,最多塞 len 個字節 |
InputStream
是一個抽象類,通過 new 它的子類 FileInputStream
來實例化
// 文件內容:hello
public static void main(String[] args) throws IOException {// 打開文件InputStream inputStream = new FileInputStream("test2.txt");// 讀取文件while (true) {int b = inputStream.read();if (b == -1) {break;}System.out.println(b);}// 關閉文件inputStream.close();
}
/*輸出:
104
101
108
108
111
*/
這正是 hello 的 ASCII 碼
要想把字節流還原成原來的文本,需要手動處理:
public static void main(String[] args) throws IOException {// 打開文件InputStream inputStream = new FileInputStream("test2.txt");// 讀取文件byte[] b = new byte[1024];int len = inputStream.read(b);// 還原成文本String s = new String(b, 0, len, StandardCharsets.UTF_8);System.out.println(s);// 關閉文件inputStream.close();
}
Reader
方法 | 說明 |
---|---|
int read(java.nio.CharBuffer target) | 嘗試將字符讀取到指定的字符緩沖區中 |
int read() | 讀取單個字符。此方法將阻塞,直到字符可用、發生I/O錯誤或到達流的末尾 |
int read(char cbuf[]) | 將字符讀取到數組中。此方法將一直阻塞,直到某個輸入可用、出現I/O錯誤或到達流的末尾 |
int read(char cbuf[], int off, int len) | 將字符讀入數組的一部分。此方法將一直阻塞,直到某個輸入可用、出現I/O錯誤或到達流的末尾 |
使用 FileReader
實例化
例:Reader 直接讀取到文本
public static void main(String[] args) throws IOException {Reader reader = new FileReader("test2.txt");char[] buffer = new char[1024];int len = reader.read(buffer);for (int i = 0; i < len; ++i) {System.out.println(buffer[i]);}reader.close();
}
其實讀文件最方便的寫法,是使用 Scanner:
這個我們在標準輸入的時候用過,只要把 System.in
換成其他 InputStream
public static void main(String[] args) throws IOException {InputStream inputStream = new FileInputStream("test2.txt");Scanner scanner = new Scanner(inputStream);String s = scanner.next();System.out.println(s);inputStream.close();
}
技巧:使用 try with resources 關閉文件
try (InputStream inputStream = new FileInputStream("test2.txt")){// ......
} catch (IOException e) {e.printStackTrace();
}
OutputStream
方法 | 說明 |
---|---|
void write(int b) | 將指定的字節寫入此輸出流 |
void write(byte b[]) | 將指定字節數組中的 b.length 個字節寫入此輸出流 |
void write(byte b[], int off, int len) | 從偏移量為 off 的指定字節數組中寫入 len 個字節到此輸出流 |
public static void main(String[] args) throws IOException {try (OutputStream outputStream = new FileOutputStream("test2.txt")) {outputStream.write('a');outputStream.write('b');outputStream.write('c');}
}
如果要輸出一個字符串,那么需要轉為字節數組:
public static void main(String[] args) throws IOException {try (OutputStream outputStream = new FileOutputStream("test2.txt")) {String s = "你好";outputStream.write(s.getBytes());}
}
注意:打開文件會清空文件內容,寫的時候并不會
Writer
方法 | 說明 |
---|---|
void write(int c) | 寫入單個字符 |
void write(char cbuf[]) | 寫入一個字符數組 |
void write(char cbuf[], int off, int len) | 寫入字符數組的一部分 |
void write(String str) | 寫入字符串 |
void write(String str, int off, int len) | 寫入字符串的一部分 |
public static void main(String[] args) throws IOException {try (Writer writer = new FileWriter("test2.txt")) {writer.write("hello world");}
}
使用 PrintWriter 包裝一下:
public static void main(String[] args) throws IOException {try (OutputStream outputStream = new FileOutputStream("test2.txt")) {PrintWriter printWriter = new PrintWriter(outputStream);// 此處 printWriter 的用法就和 System.out 類似了printWriter.println("aaa");printWriter.flush();}
}
注意:PrintWriter
自帶緩沖區,如果你寫的內容太短,可能需要 flush
一下
更多案例
文件查找
遞歸查找目錄下的所有文件,將文件名包含指定字符串的文件刪除
import java.io.*;
import java.util.Scanner;public class demo {public static void main(String[] args) throws IOException {System.out.println("請輸入要掃描的路徑:");Scanner scanner = new Scanner(System.in);String rootPath = scanner.next();File root = new File(rootPath);if (!root.exists()) {System.out.println("輸入的路徑不存在");return;}System.out.println("請輸入要刪除的文件名(或部分):");String toDelete = scanner.next();// 遞歸刪除文件scanDir(root, toDelete);}public static void scanDir(File rootDir, String toDelete) throws IOException {File[] files = rootDir.listFiles();if (files == null) {return;}for (File f : files) {if (f.isDirectory()) {scanDir(f, toDelete);} else {tryDelete(f, toDelete);}}}public static void tryDelete(File f, String toDelete) throws IOException {if (f.getName().contains(toDelete)) {System.out.println("是否刪除文件(y/n):" + f.getCanonicalPath());Scanner scanner = new Scanner(System.in);String choice = scanner.next();if (choice.equals("y")) {f.delete();}}}
}
普通文件的復制
import java.io.*;
import java.util.Scanner;public class demo {public static void main(String[] args) throws IOException {System.out.println("請輸入要復制的文件路徑:");Scanner scanner = new Scanner(System.in);String srcPath = scanner.next();File srcFile = new File(srcPath);if (!srcFile.exists()) {System.out.println("文件不存在");return;}if (!srcFile.isFile()) {System.out.println("不是普通文件");return;}System.out.println("請輸入目標路徑:");String destPath = scanner.next();File destFile = new File(destPath);if (destFile.exists()) {System.out.println("目標已經存在");return;}// 開始復制try (InputStream inputStream = new FileInputStream(srcFile);OutputStream outputStream = new FileOutputStream(destFile)) {byte[] buf = new byte[1024];while (true) {int len = inputStream.read(buf);if (len == -1) {// 拷貝完成break;}outputStream.write(buf, 0, len);}}System.out.println("復制完成");}
}