JavaSE中IO文件操作詳細(xì)指南
一、文件
1.1 文件的概念
在操作系統(tǒng)中會將“硬盤設(shè)備”和“軟件資源”都抽象成文件。
在生活中提到的文件大多指硬盤的文件(像c盤里面的文件),就是硬盤上的數(shù)據(jù)抽象而成的。
1.2 文件的操作
在計(jì)算機(jī)上文件是由操作系統(tǒng)提供的“文件系統(tǒng)”來組織管理的,操作系統(tǒng)使用“目錄”(也就是常說的文件夾)來管理文件的。目錄是一種樹形結(jié)構(gòu)
1.3 路徑
- 絕對路徑:就是以C盤D盤(C: D:)這種盤符開頭的路徑。如"E:\植物大戰(zhàn)僵尸"。
- 相對路徑:此時(shí)需要先指定一個(gè)基準(zhǔn)目錄,然后看通過什么樣的路徑來到指定文件,這個(gè)路徑就是相對路徑,用點(diǎn)開頭。此時(shí)用一個(gè)點(diǎn)表示當(dāng)前目錄,兩個(gè)點(diǎn)表示當(dāng)前目錄上一級目錄。
舉例:
假如我們要找“E:\植物大戰(zhàn)僵尸\pvzHE"目錄下的"fonts"文件。
- 如果我們當(dāng)前在“E:\植物大戰(zhàn)僵尸\pvzHE"目錄下,直接使用“.\fonts”
- 如果我們在“E:\植物大戰(zhàn)僵尸”目錄下,使用“.\pvzHE\fonts”
- 如果我們在"E:\植物大戰(zhàn)僵尸\pvzHE\新建文件夾"目錄下,使用“…\fonts”
不同場景下的基準(zhǔn)目錄:
- 在命令行操作,當(dāng)前目錄就是基準(zhǔn)目錄。
- 在idea操作項(xiàng)目目錄就是基準(zhǔn)目錄(打jar包等另行考慮)。
- 在圖形化工具上就要看實(shí)際情況了。
1.4 文件分類
在編程角度上將文件分為兩類:
- 文本文件:文件中保存的都是字符串,保存的都是合法的字符(合法的字符就是符合當(dāng)前字符集編碼的字符)。
- 二進(jìn)制文件:文件中保存的僅僅是二進(jìn)制數(shù)據(jù)。
二、Java中的文件元信息、路徑操作
Java 中通過 java.io.File 類來對一個(gè)文件(包括目錄)進(jìn)行抽象的描述。
2.1 屬性
| 修飾符及類型 | 屬性 | 說明 |
|---|---|---|
| static String | pathSeparator | 依賴于系統(tǒng)的路徑分隔符,String 類型的表示 |
| static char | pathSeparator | 依賴于系統(tǒng)的路徑分隔符,char 類型的表示 |
2.2 構(gòu)造方法
| 簽名 | 說明 |
|---|---|
| File(File parent, String child) | 根據(jù)父目錄 + 孩子文件路徑,創(chuàng)建一個(gè)新的 File 實(shí)例 |
| File(String pathname) | 根據(jù)文件路徑創(chuàng)建一個(gè)新的 File 實(shí)例,路徑可以是絕對路徑或者相對路徑 |
| File(String parent, String child) | 根據(jù)父目錄 + 孩子文件路徑,創(chuàng)建一個(gè)新的 File 實(shí)例,父目錄用路徑表示 |
2.3 方法
2.3.1 文件路徑
| 修飾符及返回值類型 | 方法簽名 | 說明 |
|---|---|---|
| String | getParent() | 返回 File 對象的父目錄文件路徑 |
| String | getName() | 返回 FIle 對象的純文件名稱 |
| String | getPath() | 返回 File 對象的文件路徑 |
| String | getAbsolutePath() | 返回 File 對象的絕對路徑 |
| String | getCanonicalPath() | 返回 File 對象的修飾過的絕對路徑 |
2.3.2 文件判斷
| 修飾符及返回值類型 | 方法簽名 | 說明 |
|---|---|---|
| boolean | exists() | 判斷 File 對象描述的文件是否真實(shí)存在 |
| boolean | isDirectory() | 判斷 File 對象代表的文件是否是一個(gè)目錄 |
| boolean | isFile() | 判斷 File 對象代表的文件是否是一個(gè)普通文件 |
| boolean | canRead() | 判斷用戶是否對文件有可讀權(quán)限 |
| boolean | canWrite() | 判斷用戶是否對文件有可寫權(quán)限 |
2.3.3 文件創(chuàng)建刪除
| 修飾符及返回值類型 | 方法簽名 | 說明 |
|---|---|---|
| boolean | createNewFile() | 根據(jù) File 對象,自動創(chuàng)建一個(gè)空文件。成功創(chuàng)建后返回 true |
| boolean | delete() | 根據(jù) File 對象,刪除該文件。成功刪除后返回 true |
| void | deleteOnExit() | 根據(jù) File 對象,標(biāo)注文件將被刪除,刪除動作會到JVM 運(yùn)行結(jié)束時(shí)才會進(jìn)行 |
2.3.4 其他操作
| 修飾符及返回值類型 | 方法簽名 | 說明 |
|---|---|---|
| String[ ] | list() | 返回 File 對象代表的目錄下的所有文件名 |
| File[ ] | listFiles() | 返回 File 對象代表的目錄下的所有文件,以 File 對象表示 |
| boolean | mkdir() | 創(chuàng)建 File 對象代表的目錄 |
| boolean | mkdirs() | 創(chuàng)建 File 對象代表的目錄,如果必要,會創(chuàng)建中間目錄 |
| boolean | renameTo(Filedest) | 進(jìn)行文件改名,也可以視為我們平時(shí)的剪切、粘貼操作 |
三、文件讀寫操作
在Java中對文件的讀寫操作使用流對象(stream)
3.1 流(Stream)
在標(biāo)準(zhǔn)庫中提供的文件讀寫操作的類有很多,但可以分為兩類。
3.1.1 字節(jié)流
字節(jié)流對應(yīng)著二進(jìn)制文件,每次讀寫的最小單位都是字節(jié)(Byte)。
字節(jié)流提供了兩個(gè)父類(InputStream)(OutputStream)來供繼承。
3.1.1.1 InputStream
InputStream在源碼中是一個(gè)抽象類,不能直接new對象。提供了一個(gè)子類FileInputStream。

類需要傳文件路徑,如果文件沒找到還會拋出FileNotFoundException異常。

方法簡介
| 返回值 | 方法簽名 | 說明 |
|---|---|---|
| int | read() | 讀取一個(gè)字節(jié)的數(shù)據(jù),返回 -1 代表已經(jīng)完全讀完了 |
| int | read(byte[ ] b) | 最多讀取 b.length 字節(jié)的數(shù)據(jù)到 b 中,返回實(shí)際讀到的數(shù)量;-1 代表以及讀完了 |
| int | read(byte[ ] b, int off, int len) | 最多讀取 len - off 字節(jié)的數(shù)據(jù)到 b 中,放在從 off 開始,返回實(shí)際讀到的數(shù)量;-1 代表以及讀完了 |
| void | close() | 關(guān)閉字節(jié)流 |
3.1.1.2 OutputStream
默認(rèn)打開一個(gè)文件會先清空,要繼續(xù)寫不清空在創(chuàng)建對象時(shí)傳入true作為第二個(gè)參數(shù)。

OutputStream在源碼中是一個(gè)抽象類,不能直接new對象。提供了一個(gè)子類FileOutputStream。

類需要傳文件路徑,如果文件沒找到還會拋出FileNotFoundException異常。

方法
| 返回值 | 方法簽名 | 說明 |
|---|---|---|
| void | write(int b) | 寫入要給字節(jié)的數(shù)據(jù) |
| void | write(byte[ ] b) | 將 b 這個(gè)字符數(shù)組中的數(shù)據(jù)全部寫入 os 中 |
| int | write(byte[ ] b, int off, int len) | 將 b 這個(gè)字符數(shù)組中從 off 開始的數(shù)據(jù)寫入 os 中,一共寫 len 個(gè) |
| void | close() | 關(guān)閉字節(jié)流 |
| void | flush() | 重要:我們知道 I/O 的速度是很慢的,所以,大多的 OutputStream 為了減少設(shè)備操作的次數(shù),在寫數(shù)據(jù)的時(shí)候都會將數(shù)據(jù)先暫時(shí)寫入內(nèi)存的一個(gè)指定區(qū)域里,直到該區(qū)域滿了或者其他指定條件時(shí)才真正將數(shù)據(jù)寫入設(shè)備中,這個(gè)區(qū)域一般稱為緩沖區(qū)。但造成一個(gè)結(jié)果,就是我們寫的數(shù)據(jù),很可能會遺留一部分在緩沖區(qū)中。需要在最后或者合適的位置,調(diào)用 flush(刷新)操作,將數(shù)據(jù)刷到設(shè)備中。 |
3.1.2 字符流
字符流對應(yīng)著文本文件,每次讀寫的最小單位是字符(根據(jù)當(dāng)前字符集來,一個(gè)中文字符在utf8就是3字節(jié),GBK就是兩字節(jié))。
字符流就相當(dāng)于對字節(jié)流進(jìn)行了一個(gè)封裝,自動幫我們把字節(jié)流中相鄰幾個(gè)字節(jié)轉(zhuǎn)換成字符。
字符流提供了兩個(gè)父類(Reader)(Writer)來供繼承。
3.1.2.1 Reader
Reader在源碼中是一個(gè)抽象類,不能直接new對象。提供了一個(gè)子類FileReader。

FileReader類需要傳文件路徑,如果文件沒找到還會拋出FileNotFoundException異常。

Reader中讀取字符常用是read方法,都會拋出IOException異常,介紹常用3種。
| 返回值 | 分法簽名 | 說明 |
|---|---|---|
| int | read() | 讀取一個(gè)字符,讀取到返回ASCII值或者字符集編碼值,沒讀取到返回-1 |
| int | read(char[ ] cbuf) | 讀取多個(gè)字符,盡量將cbuf數(shù)組填滿,返回讀取到的字符個(gè)數(shù),如果讀完文件返回-1 |
| int | read(char[ ] cbuf, int off, int len) | l最多讀len-off個(gè),從數(shù)組off下標(biāo)開始儲存,返回讀到的個(gè)數(shù),如果讀完文件返回-1 |
返回值說明:
int作為返回值時(shí),返回的是一個(gè)2字節(jié)表示的,這時(shí)因?yàn)樵贘ava中char類型是Unicode編碼,而String是由utf8編碼(String的編碼集可改)。

創(chuàng)建了一個(gè)Reader對象要釋放:對象名.close();主要釋放的是文件描述符表(在進(jìn)程介紹PCB的主要屬性),文件描述符表里面主要用順序表(數(shù)組)來儲存,如果一直不釋放,里面數(shù)組被占滿就會發(fā)生內(nèi)存泄露。
但是如果直接就這么寫,那如果上面代碼拋出異常,就執(zhí)行不到close,改進(jìn)方法:
- try-finally處理:
Reader reader = new FileReader("d:/test.txt");
try {
int n = reader.read();
} finally {
reader.close();
}
- try with resource
在定義對象時(shí)放入,出了try語句就會自動調(diào)用類實(shí)現(xiàn)的close方法(必須是實(shí)現(xiàn)了closeable接口的)。
try( Reader reader = new FileReader("d:/test.txt") ) {
int n = reader.read();
}
3.1.2.2 Writer
默認(rèn)打開一個(gè)文件會先清空,要繼續(xù)寫不清空在創(chuàng)建對象時(shí)傳入true作為第二個(gè)參數(shù)。

InputStream在源碼中是一個(gè)抽象類,不能直接new對象。提供了一個(gè)子類FileInputStream。

類需要傳文件路徑,如果文件沒找到還會拋出IOException異常。

方法
| 返回值 | 方法簽名 | 說明 |
|---|---|---|
| void | write(int c) | 寫入要給文件的數(shù)據(jù) |
| void | write(char[ ] cbuf) | 將 cbuf 這個(gè)字符數(shù)組中的數(shù)據(jù)全部寫入 os 中 |
| int | write(byte[ ] cbuf, int off, int len) | 將 cbuf 這個(gè)字符數(shù)組中從 off 開始的數(shù)據(jù)寫入 os 中,一共寫 len 個(gè) |
| void | write(String str) | 將 str 這個(gè)字符串中的數(shù)據(jù)全部寫入 os 中 |
| void | write(String str, int off, int len) | 將 str 這個(gè)字符串中的數(shù)據(jù)從 off 開始的數(shù)據(jù)寫入 os 中,一共寫 len 個(gè) |
| void | close() | 關(guān)閉字節(jié)流 |
| void | flush() | 重要:我們知道 I/O 的速度是很慢的,所以,大多的 OutputStream 為了減少設(shè)備操作的次數(shù),在寫數(shù)據(jù)的時(shí)候都會將數(shù)據(jù)先暫時(shí)寫入內(nèi)存的一個(gè)指定區(qū)域里,直到該區(qū)域滿了或者其他指定條件時(shí)才真正將數(shù)據(jù)寫入設(shè)備中,這個(gè)區(qū)域一般稱為緩沖區(qū)。但造成一個(gè)結(jié)果,就是我們寫的數(shù)據(jù),很可能會遺留一部分在緩沖區(qū)中。需要在最后或者合適的位置,調(diào)用 flush(刷新)操作,將數(shù)據(jù)刷到設(shè)備中。 |
3.2 字節(jié)流字符流轉(zhuǎn)換
使用Scanner工具類去讀取文件中的字符。
try(InputStream inputStream = new FileInputStream("D:/test.txt")) {
Scanner scanner = new Scanner(inputStream);
String s = scanner.next();
}
使用PrintWriter工具類去寫入文件中的字符。
try(OutputStream outputStream = new FileOutputStream("D:/test.txt",true)) {
PrintWriter printWriter = new PrintWriter(outputStream);
printWriter.println();
}
四、自定義快讀類
自定義快讀類來解決我們做算法題的時(shí)候由于數(shù)據(jù)量過大的時(shí)候引起的超時(shí)問題。
4.1 自定義快速讀入
我們使用Scanner去讀IO設(shè)備文件,,而我們現(xiàn)在使用BufferedReader來開辟一個(gè)內(nèi)存緩沖區(qū),在內(nèi)存中拿數(shù)據(jù)比IO設(shè)備要快得多。
步驟:
- 字節(jié)流轉(zhuǎn)變?yōu)樽址鳎诖嫒雰?nèi)存緩沖區(qū)中。
BufferedReader bf = new BufferedReader(new InputStreamReader(system.in));
- 字符串裁剪對象,拿到內(nèi)存緩沖區(qū)的字符串的必要對象。
StringTokenizer st = new StringTokenizer("");
- 詳解next方法:相當(dāng)于在內(nèi)存緩沖區(qū)中拿一行數(shù)據(jù),使用while循環(huán)來處理多行輸入。
String next() throws IOException {
while(!st.hasMoreTokens()) {
st = new StringTokenizer(bf.readLine());
}
return st.nextToken();
}
- 其他直接返回對應(yīng)的parse轉(zhuǎn)換就行。
類代碼:
import java.util.StringTokenizer;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
class Read {
StringTokenizer st = new StringTokenizer("");
BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
String next() throws IOException {
while(!st.hasMoreTokens()) {
st = new StringTokenizer(bf.readLine());
}
return st.nextToken();
}
String nextLine() throws IOException {
return bf.readLine();
}
int nextInt() throws IOException {
return Integer.parseInt(next());
}
long nextLong() throws IOException {
return Long.parseLong(next());
}
double nextDouble() throws IOException {
return Double.parseDouble(next());
}
float nextFloat() throws IOException {
return Float.parseFloat(next());
}
}
4.2 自定義快速輸出
跟自定義一樣的優(yōu)化方式。
public static PrintWriter out = new PrintWriter(new BufferedWriter(new OutPutStreamWriter(System.out)))
使用之后就直接 out.輸出方法,輸出方法與System.out一樣。
總結(jié)
到此這篇關(guān)于JavaSE中IO文件操作的文章就介紹到這了,更多相關(guān)JavaSE IO文件操作內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Redisson分布式鎖實(shí)現(xiàn)原理示例詳解
Redisson分布式鎖通過Lua腳本保證原子性操作,實(shí)現(xiàn)了分布式互斥、可重入、自動續(xù)期等核心特性,其高級特性包括公平鎖、讀寫鎖和紅鎖算法,能夠滿足不同場景下的并發(fā)控制需求,這篇文章主要介紹了Redisson分布式鎖實(shí)現(xiàn)原理的相關(guān)資料,需要的朋友可以參考下2026-04-04
SpringBoot是如何實(shí)現(xiàn)自動配置的你知道嗎
這篇文章主要介紹了詳解SpringBoot自動配置原理,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2021-08-08
SpringBoot整合TomCat實(shí)現(xiàn)本地圖片服務(wù)器代碼解析
這篇文章主要介紹了SpringBoot整合TomCat實(shí)現(xiàn)本地圖片服務(wù)器代碼解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-08-08
SpringBoot項(xiàng)目的兩種發(fā)布方式
本文主要介紹了SpringBoot項(xiàng)目的兩種發(fā)布方式,包含jar包發(fā)布和war包發(fā)布,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2024-07-07
Java+mysql實(shí)現(xiàn)學(xué)籍管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了Java+mysql實(shí)現(xiàn)學(xué)籍管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-07-07
SpringBoot中使用JWT的實(shí)戰(zhàn)
本文主要介紹了SpringBoot中使用JWT的實(shí)戰(zhàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-06-06
@EnableWebMvc介紹和使用詳細(xì)demo(最新推薦)
@EnableWebMvc是SpringMVC的一個(gè)注解,用于啟用SpringMVC框架的基本功能,它通常用于需要自定義SpringMVC配置或禁用SpringBoot自動配置的場景,本文給大家介紹了@EnableWebMvc介紹和使用詳細(xì)demo,感興趣的朋友一起看看吧2025-01-01

