前言
在變數、陣列和物件中儲存的資料是暫時存在的,程式結束後它們就會遺失。為了能夠永久保存已建立的數據,需要將其保存在磁碟檔案中,這樣就可以在其他程式中使用它們。 Java的I/O技術可以將資料保存到文字檔案、二進位檔案甚至是ZIP壓縮檔案中,已達到永久性保存資料的要求。掌握I/O處理技術能夠提升對資料的處理能力。
一、流概述
流是一組有序的資料序列,根據操作的類型,可分為輸入流和輸出流兩種。 I/O(Input/Output,輸入/輸出)流提供了一條通道程序,可以使用這條通道把來源中的位元組序列送到目的地。雖然I/O流通常與磁碟檔案存取有關,但是程式的來源和目的地也可以是鍵盤、滑鼠、記憶體或顯示器視窗等。
Java由資料流處理輸入/輸出模式,程式從指向來源的輸入流讀取來源中的數據,來源可以是檔案、網路、壓縮套件或其他資料來源。
輸出流的指向是資料要到達的目的地,程式透過寫入資料流寫入資料把訊息到目的地。
二、輸入/輸出流
Java語言定義了許多類別專門負責各種方式的輸入/輸出,這類類別都被放在java.io套件中。其中,所有輸入流類別都是抽象類別InputStream(位元組輸入流)或抽象類別Reader(字元輸入流)的子類別;而所有輸出流都是抽象類別OutputStream(位元組輸出流)或抽象類別Writer(字元輸出流)的子類別。
1、輸入流
InputStream類別是位元組輸入流的抽象類,是所有位元組輸入流的父類。 InputStream類別的具體層次結構如下所示。
該類別中所有方法遇到錯誤時都會引發IOException異常。下面是對該類別中的一些方法的簡要說明。
read()方法:從輸入流讀取資料的下一個位元組。傳回0-255範圍內的int位元組值。如果因為已經到達流末尾而沒有可用的字節,則傳回值為-1。
read(byte[] b):從輸入流中讀入一定長度的位元組,並以整數的形式傳回位元組數。
mark(int readlimit)方法:在輸入流的目前位置放置一個標記,readlimit參數告知此輸入流在標記位置失效之前允許讀取的位元組數。
reset()方法:將輸入指標傳回目前所做的標記處。
skip(long n)方法:跳過輸入流上的n個位元組並傳回實際跳過的位元組數。
markSupported()方法:如果目前流支援mark()/reset()操作就回傳true。
close方法:關閉此輸入流並釋放與該流關聯的所有系統資源。
Java中的字元是Unicode編碼,是雙位元組的。 InputStream是用來處理位元組的,而且不適合處理字元文字。 Java為字元文字的輸入特別提供了一套單獨的類別Reader,但Reader類別並不是InputStream類別的替換者,只是處理字串時簡化了程式設計。 Reader類別是字元輸入流的抽象類別,所有字元輸入流的實作都是它的子類別。
Reader類別中的方法與InputStream類別中的方法類似,讀者在需要時可查看JDK文檔。
2、輸出流
OutputStream類別是位元組輸出流的抽象類,此抽象類別是表示輸出位元組流的所有類別的超類別。
OutputStream類別中的所有方法均傳回void,在遇到錯誤時會引發IoException異常。以下對OutputStream類別中的方法作簡單的介紹。
write(int b)方法:將指定的位元組寫入此輸出流。
write(byte[] b)方法:將b個位元組從指定的byte陣列寫入此輸出流。
write(byte[] b,int off, int len)方法:將指定byte數組中從偏移量off開始的len個位元組寫入此輸出流。
flush()方法:徹底完成輸出並清空快取區。
close()方法:關閉輸出流。
三、File類別
File類別是java.io套件中唯一代表磁碟檔案本身的物件。 File類別定義了一些與平台無關的方法來操作文件,可以透過呼叫File類別中的方法,實現創建、刪除、重新命名文件等操作。 File類別的物件主要用來取得檔案本身的一些訊息,如檔案所在的目錄、檔案的長度、檔案讀寫權限等。資料流可以將資料寫入到檔案中,檔案也是資料流最常用的資料媒體。
1、檔案的建立與刪除
可以使用File類別建立一個檔案物件。通常使用以下3種構造方法來建立文件物件。
1、File(String pathname)
此建構方法透過將給定路徑名字串轉換為抽象路徑名來建立一個新File實例。
語法如下:
new File(String pathname);
其中,pathname指定路徑名稱(包含檔案名稱)。例如:
File file = new File(“d:/1.txt”);
2、File(String parent,String child)
此建構方法根據定義的父路徑和子路徑字串(包含檔案名稱)建立一個新的File物件。
語法如下:
new File(String parent,String child);
3、File(File f,String child)
此建構方法根據Parent抽象路徑名和child路徑名稱字串建立新的File實例。
語法如下:
new File(File f,String child);
2、取得檔案資訊
File類提供了很多方法用於獲取一些文件本身的資訊。如下表
方法| 傳回值| 說明
-------- | -----
getName() | String| 取得檔案的名稱
canReda()| boolean |判斷檔案是否為可讀的
canWrite()| boolean | 判斷檔案是否可寫入
exits()|boolean | 判斷檔案是否存在
length()|long | 取得檔案的長度(以位元組為單位)
getAbsolutePath() | String | 取得檔案的絕對路徑
getParent() | String | 取得檔案的父路徑
isFile() | boolean | 判斷文件是否存在
isDirectory() | boolean | 判斷檔案是否為一個目錄
isHidden() | boolean | 判斷檔案是否為隱藏檔案
lastModified() | long | 取得檔案最後修改時間
四、檔案輸入/輸出流
程式運作期間,大部分資料都在記憶體中進行操作,當程式結束或關閉時,這些資料將會消失。如果需要將資料永久保存,可使用文件輸入/輸出流與指定的文件建立連接,將所需的資料永久保存到文件中。
1、FillInputStream與FileOutputStream類別
FileInputStream類別與FileOUtputStream類別都用來操作磁碟檔案。如果使用者的檔案讀取需求比較簡單,則可以使用FileInputString類,則該類別繼承自InputString類別。 FileOutputStream類別與FileInputStream類別對應,提供了基本的檔案寫入能力。 FileOutputStream類別是OutputStream類別的子類別。
FileInputStream類別常用的建構方法如下:
FileInputStream(String name)
FileInputStream(File file)
2、FileReader和FileWriter類別
使用FileOutputStream類別向檔案中寫入資料與使用FileInputStream類別從檔案中將內容讀出來,都存在一點不足,即這兩個類別都只提供了對位元組或位元組數組的讀取方法。由於漢子在檔案中佔用兩個位元組,如果使用位元組流,讀取不好可能會出現亂碼現象,此時採用字元流Reader或Writer類別即可避免這種現象。
FileReader和FileWriter字元流對應了FileInputStream和FileOutputStream類別。 FileReader流依序讀取文件,只要不關閉流,每次呼叫read()方法就會依序讀取來源中其餘的內容,直到來源的末端或流被關閉。
五、有快取的輸入/輸出流
快取是I/O的一種效能最佳化。快取流為I/O流增加了記憶體快取區。有了快取區,使得在流上執行skip()、mark()和reset()方法都成為可能。
1、BufferedInputStream與BufferedOutputStream類別
BufferedInputStream類別可以對所有InputStream類別進行緩衝區的包裝以達到效能的最佳化。 BufferedInputStream類別有兩個建構方法:
BufferedInputStream(InputStream in)
BufferedInputStream(InputStream in,int size)
#第一種建構方法來建立一個有32個位元組的快取區,第二種建構方法以指定的大小來建立快取區。
2、BufferedReader與BufferedWriter類別
BufferedReader類別與BufferedWriter類別分別繼承Reader類別與Writer類別。這兩個類別同樣具有內部快取機制,並且可以以行為單位進行輸入/輸出。
六、資料輸入/輸出流
資料輸入/輸出流(DataInputStream類別與DataOutputStream類別)允許應用程式以與機器無關的方式從底層輸入流中讀取基本Java數據類型。也就是說,當讀取一個資料時,就不必再關心這個數值應該是哪種位元組。
七、ZIP壓縮輸入/輸出流
ZIP壓縮管理檔(ZIP archive)是一種十分典型的檔案壓縮形式,使用它可以節省儲存空間。關於ZIP壓縮的I/O實現,在Java的內建類別中提供了非常好用的相關類,所以其實現方式非常簡單。本節將介紹使用java.util.zip套件中的ZipOutputStream與ZipInputStream類別來實作檔案的壓縮/解壓縮。如要從ZIP壓縮管理文件內讀取某個文件,要先找到對應文件的「目錄進入點」(從它可知該文件在ZIP文件內的位置),才能讀取這個文件的內容。如果要將檔案內容寫入ZIP檔案內,必須先寫入對應於該檔案的“目錄進入點”,並且將要寫入檔案內容的位置移到此進入點所指的位置,然後再寫入文件內容。
Java实现了I/O数据流与网络数据流的单一接口,因此数据的压缩、网络传输和解压缩的实现比较容易。ZipEntry类产生的对象,是用来代表一个ZIP压缩文件内的进入点(entry)。ZipInputStream用来写出ZIP压缩格式的文件,所支持的包括已压缩及未压缩的进入点(entry)。
ZipOutputStream类用来写出ZIp压缩格式的文件,而且所支持的包括已压缩及未压缩的进入点(entry)。下面介绍利用ZipEntry、
ZipInputStream和ZipOutputStream3个Java类实现ZIP数据压缩方式的编程方法。
1、压缩文件
利用ZipOutputStream类对象,可将文件压缩为.zip文件。ZipOutputStream类的构造方法如下:
ZipOutputStram(OutputStream out);
ZipOutputStream类的常用方法如表所示:
方法 | 返回值 | 说明 |
---|---|---|
putNextEntry(ZipEntry e) | void | 开始写一个新的ZipEntry,并将流内的位置移至此entry所指数据的开头 |
write(byte[] b,int off,int len) | void | 将字节数组写入当前ZIP条目数据 |
finish() | void | 完成写入ZIP输出流的内容,无须关闭它所配合的OutputStream |
setComment(String comment) | void | 可设置此ZIP文件的注释文字 |
2、解压缩ZIP文件
ZipInputStream类可读取ZIP压缩格式的文件,包括已压缩和未压缩的条目(entry)。ZipInputStream类的构造方法如下:
ZipInputStream(InputStream in)
ZipInputStream类的常用方法如下表所示:
方法 | 返回值 | 说明 |
---|---|---|
read(byte[] b, int off , int len) | int | 读取目标b数组内off偏移量的位置,长度是len字节 |
available() | int | 判断是否已读完目前entry所指定的数据。已读完返回0,否则返回1 |
closeEntry() | void | 关闭当前ZIP条目并定位流以读取下一个条目 |
skip(long n) | long | 跳过当前ZIP条目中指定的字节数 |
getNextEntry() | ZipEntry | 读取下一个ZipEntry,并将流内的位置移至该entry所指数据的开头 |
createZipEntry(String name) | ZipEntry | 以指定的name参数新建一个ZipEntry对象 |
补充:获取目录下的所有目录和文件
示例:假设目录“D:\TestDir1”下有两个文件夹(dir1 和 dir2)和一个文件 file1.txt 。
File[] listFiles()方法:获取该目录下的所有子目录和文件,返回File类数组。
import java.io.File; /** * 获取目录下的所有目录和文件 * @author pan_junbiao **/ public class DirFileTest { public static void main(String[] args) { File file = new File("D:\\TestDir1"); //判断目录是否存在 if (!file.exists()) { System.out.println("目录不存在"); return; } //获取文件数组 File[] fileList = file.listFiles(); for (int i = 0; i < fileList.length; i++) { //判断是否为目录 if (fileList[i].isDirectory()) { System.out.println("目录:" + fileList[i].getName()); } else { System.out.println("文件:" + fileList[i].getName()); } } } }
执行结果:
以上是Java中I/O輸入輸出實例分析的詳細內容。更多資訊請關注PHP中文網其他相關文章!

javaispopularforcross-platformdesktopapplicationsduetoits“ writeonce,runany where”哲學。 1)itusesbytiesebyTecodeThatrunsonAnyJvm-備用Platform.2)librarieslikeslikeslikeswingingandjavafxhelpcreatenative-lookingenative-lookinguisis.3)

在Java中編寫平台特定代碼的原因包括訪問特定操作系統功能、與特定硬件交互和優化性能。 1)使用JNA或JNI訪問Windows註冊表;2)通過JNI與Linux特定硬件驅動程序交互;3)通過JNI使用Metal優化macOS上的遊戲性能。儘管如此,編寫平台特定代碼會影響代碼的可移植性、增加複雜性、可能帶來性能開銷和安全風險。

Java將通過雲原生應用、多平台部署和跨語言互操作進一步提昇平台獨立性。 1)雲原生應用將使用GraalVM和Quarkus提升啟動速度。 2)Java將擴展到嵌入式設備、移動設備和量子計算機。 3)通過GraalVM,Java將與Python、JavaScript等語言無縫集成,增強跨語言互操作性。

Java的強類型系統通過類型安全、統一的類型轉換和多態性確保了平台獨立性。 1)類型安全在編譯時進行類型檢查,避免運行時錯誤;2)統一的類型轉換規則在所有平台上一致;3)多態性和接口機制使代碼在不同平台上行為一致。

JNI會破壞Java的平台獨立性。 1)JNI需要特定平台的本地庫,2)本地代碼需在目標平台編譯和鏈接,3)不同版本的操作系統或JVM可能需要不同的本地庫版本,4)本地代碼可能引入安全漏洞或導致程序崩潰。

新興技術對Java的平台獨立性既有威脅也有增強。 1)雲計算和容器化技術如Docker增強了Java的平台獨立性,但需要優化以適應不同雲環境。 2)WebAssembly通過GraalVM編譯Java代碼,擴展了其平台獨立性,但需與其他語言競爭性能。

不同JVM實現都能提供平台獨立性,但表現略有不同。 1.OracleHotSpot和OpenJDKJVM在平台獨立性上表現相似,但OpenJDK可能需額外配置。 2.IBMJ9JVM在特定操作系統上表現優化。 3.GraalVM支持多語言,需額外配置。 4.AzulZingJVM需特定平台調整。

平台獨立性通過在多種操作系統上運行同一套代碼,降低開發成本和縮短開發時間。具體表現為:1.減少開發時間,只需維護一套代碼;2.降低維護成本,統一測試流程;3.快速迭代和團隊協作,簡化部署過程。


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

WebStorm Mac版
好用的JavaScript開發工具

DVWA
Damn Vulnerable Web App (DVWA) 是一個PHP/MySQL的Web應用程序,非常容易受到攻擊。它的主要目標是成為安全專業人員在合法環境中測試自己的技能和工具的輔助工具,幫助Web開發人員更好地理解保護網路應用程式的過程,並幫助教師/學生在課堂環境中教授/學習Web應用程式安全性。 DVWA的目標是透過簡單直接的介面練習一些最常見的Web漏洞,難度各不相同。請注意,該軟體中

SublimeText3 英文版
推薦:為Win版本,支援程式碼提示!

EditPlus 中文破解版
體積小,語法高亮,不支援程式碼提示功能

記事本++7.3.1
好用且免費的程式碼編輯器