- 資訊首頁(yè) > 開(kāi)發(fā)技術(shù) > 編程語(yǔ)言 >
- Java基礎之文件概述
下面,我們先介紹一些基本概念和常識,包括二進(jìn)制思維、文件類(lèi)型、文本文件的編碼、文件系統和文件讀寫(xiě)等。
為了透徹理解文件,我們首先要有一個(gè)二進(jìn)制思維。 所有文件, 不論是可執行文件、圖片文件、視頻文件、Word文件、壓縮文件、txt 文件,都沒(méi)什么可神秘的,它們都是以0和1的二進(jìn)制形式保存的。我們 所看到的圖片、視頻、文本,都是應用程序對這些二進(jìn)制的解析結果。
作為程序員,我們應該有一個(gè)編輯器,能查看文件的二進(jìn)制形式, 比如UltraEdit,它支持以十六進(jìn)制進(jìn)行查看和編輯。比如,一個(gè)文本文 件,看到的內容為:
打開(kāi)十六進(jìn)制編輯,看到的內容如圖所示。
左邊的部分就是其對應的十六進(jìn)制,“hello"對應的十六進(jìn)制 是"68656C 6C 6F”,對應ASCII碼編號"104101108108111",“馬"對應的 十六進(jìn)制是"E9A9AC”,這是"馬"的UTF-8編碼。
雖然所有數據都是以二進(jìn)制形式保存的,但為了方便處理數據,高 級語(yǔ)言引入了數據類(lèi)型的概念。文件處理也類(lèi)似,所有文件都是以二進(jìn) 制形式保存的,但為了便于理解和處理文件,文件也有文件類(lèi)型的概 念。
文件類(lèi)型通常以擴展名的形式體現,比如,PDF文件類(lèi)型的擴展名 是.pdf,圖片文件的一種常見(jiàn)擴展名是.jpg,壓縮文件的一種常見(jiàn)擴展名 是.zip。每種文件類(lèi)型都有一定的格式,代表著(zhù)文件含義和二進(jìn)制之間的映射關(guān)系。比如一個(gè)Word文件,其中有文本、圖片、表格,文本可 能有顏色、字體、字號等,doc文件類(lèi)型就定義了這些內容和二進(jìn)制表 示之間的映射關(guān)系。有的文件類(lèi)型的格式是公開(kāi)的,有的可能是私有 的,我們也可以定義自己私有的文件格式。
對于一種文件類(lèi)型,往往有一種或多種應用程序可以解讀它,進(jìn)行 查看和編輯,一個(gè)應用程序往往可以解讀一種或多種文件類(lèi)型。在操作 系統中,一種擴展名往往關(guān)聯(lián)一個(gè)應用程序,比如.doc后綴關(guān)聯(lián)Word應 用。用戶(hù)通過(guò)雙擊試圖打開(kāi)某擴展名的文件時(shí),操作系統查找關(guān)聯(lián)的應 用程序,啟動(dòng)該程序,傳遞該文件路徑給它,程序再打開(kāi)該文件。
需要說(shuō)明的是,給文件加正確的擴展名是一種慣例,但并不是強制 的,如果擴展名和文件類(lèi)型不匹配,應用程序試圖打開(kāi)該文件時(shí)可能會(huì ) 報錯。另外,一個(gè)文件可以選擇使用多種應用程序進(jìn)行解讀,在操作系 統中,一般通過(guò)右鍵單擊文件,選擇打開(kāi)方式即可。
文件類(lèi)型可以粗略分為兩類(lèi):一類(lèi)是文本文件;另一類(lèi)是二進(jìn)制文件。文本文件的例子有普通的文本文件(.txt),程序源代碼文件 (.java)、HTML文件(.html)等;二進(jìn)制文件的例子有壓縮文件 (.zip)、PDF文件(.pdf)、MP3文件(.mp3)、Excel文件(.xlsx) 等。
基本上,文本文件里的每個(gè)二進(jìn)制字節都是某個(gè)可打印字符的一部分,都可以用最基本的文本編輯器進(jìn)行查看和編輯,如Windows上的notepad、Linux上的vi。二進(jìn)制文件中,每個(gè)字節就不一定表示字符, 可能表示顏色、字體、聲音大小等,如果用基本的文本編輯器打開(kāi),一 般都是滿(mǎn)屏的亂碼,需要專(zhuān)門(mén)的應用程序進(jìn)行查看和編輯。
對于文本文件,我們還必須注意文件的編碼方式。文本文件中包含 的基本都是可打印字符,但字符到二進(jìn)制的映射(即編碼)卻有多種方 式,如GB18030、UTF-8,我們在第2章詳細介紹過(guò)各種編碼,這里就不 贅述了。
對于一個(gè)給定的文本文件,它采用的是什么編碼方式呢?一般而言,我們是不知道的。那應用程序用什么編碼方式進(jìn)行解讀呢?一般使 用某種默認的編碼方式,可能是應用程序默認的,也可能是操作系統默 認的,當然也可能采用一些比較智能的算法自動(dòng)推斷編碼方式。
對于UTF-8編碼的文件,我們需要特別說(shuō)明。有一種方式,可以標 記該文件是UTF-8編碼的,那就是在文件最開(kāi)頭加入三個(gè)特殊字節 (0xEF 0xBB 0xBF),這三個(gè)特殊字節被稱(chēng)為BOM頭,BOM是Byte Order Mark(即字節序標記) 的縮寫(xiě)。比如,對前面的hello.txt文件,帶 BOM頭的UTF-8編碼的十六進(jìn)制形式如圖13-2所示。
圖13-1和圖13-2所示都是UTF-8編碼,看到的字符內容也一樣,但 二進(jìn)制內容不一樣,一個(gè)帶BOM頭,一個(gè)不帶BOM頭。
需要注意的是,不是所有應用程序都支持帶BOM頭的UTF-8編碼文件,比如PHP就不支持BOM,如果PHP源代碼文件帶BOM頭,PHP運行 就會(huì )出錯。碰到這種問(wèn)題時(shí),前面介紹的二進(jìn)制思維就特別重要,不要只看文件的顯示,還要看文件背后的二進(jìn)制。
另外,我們需要說(shuō)明下文本文件的換行符。在Windows系統中,換 行符一般是兩個(gè)字符"\r\n",即ASCII碼的13('\r')和10('\n'),在 Linux系統中,換行符一般是一個(gè)字符"\n"。
文件一般是放在硬盤(pán)上的,一個(gè)機器上可能有多個(gè)硬盤(pán),但各種操作系統都會(huì )隱藏物理硬盤(pán)概念,提供一個(gè)邏輯上的統一結構。在 Windows中,可以有多個(gè)邏輯盤(pán),如C、D、E等,每個(gè)盤(pán)可以被格式化 為一種不同的文件系統,常見(jiàn)的文件系統有FAT32和NTFS。在Linux 中,只有一個(gè)邏輯的根目錄,用斜線(xiàn)/表示。Linux支持多種不同的文件 系統,如Ext2/Ext3/Ext4等。不同的文件系統有不同的文件組織方式、 結構和特點(diǎn),不過(guò),一般編程時(shí),語(yǔ)言和類(lèi)庫為我們提供了統一的 API,我們并不需要關(guān)心其細節。
在邏輯上,Windows中有多個(gè)根目錄,Linux中有一個(gè)根目錄,每 個(gè)根目錄下有一棵子目錄和文件構成的樹(shù)。每個(gè)文件都有文件路徑 的概念,路徑有兩種形式:一種是絕對路徑 ,另一種是相對路徑 。
所謂絕對路徑,是從根目錄開(kāi)始到當前文件的完整路徑,在 Windows中,目錄之間用反斜線(xiàn)分隔,如C:\code\hello.java,在Linux 中,目錄之間用斜線(xiàn)分隔,如/Users/laoma/Desktop/code/hello.java。在 Java中,java.io.File類(lèi)定義了一個(gè)靜態(tài)變量File.separator,表示路徑分隔 符,編程時(shí)應使用該變量而避免硬編碼。
所謂相對路徑,是相對于當前目錄 而言的。在命令行終端上,通 過(guò)cd命令進(jìn)入的目錄就是當前目錄;在Java中,通過(guò) System.getProperty(“user.dir”)可以得到運行Java程序的當前目錄。相對路徑不以根目錄開(kāi)頭,比如在Windows上,當前目錄為D:\laoma, 相對路徑為code\hello.java,則完整路徑為D:\laoma\code\hello.java。
每個(gè)文件除了有具體內容,還有元數據信息 ,如文件名、創(chuàng )建時(shí) 間、修改時(shí)間、文件大小等。文件還有一個(gè)是否隱藏 的性質(zhì)。在Linux 系統中,如果文件名以.開(kāi)頭,則為隱藏文件;在Windows系統中,隱藏 是文件的一個(gè)屬性,可以進(jìn)行設置。
大部分文件系統的文件和目錄具有訪(fǎng)問(wèn)權限 的概念,對所有者、 用戶(hù)組可以有不同的權限,具體權限包括讀、寫(xiě)、執行。
文件名有大小寫(xiě)是否敏感 的概念。在Windows系統中,一般是大小 寫(xiě)不敏感的,而Linux則一般是大小寫(xiě)敏感的。也就是說(shuō),同一個(gè)目錄下,abc.txt和ABC.txt在Windows中被視為同一個(gè)文件,而在Linux中則 被視為不同的文件。
操作系統中有一個(gè)臨時(shí)文件 的概念。臨時(shí)文件位于一個(gè)特定目 錄,比如Windows 7中,臨時(shí)文件一般位于“C:\Users\用戶(hù)名 \AppData\Local\Temp”;Linux系統中,臨時(shí)文件位于/tmp。操作系統會(huì )有一定的策略自動(dòng)清理不用的臨時(shí)文件。臨時(shí)文件一般不是用戶(hù)手工創(chuàng )建的,而是應用程序產(chǎn)生的,用于臨時(shí)目的。
文件是放在硬盤(pán)上的,程序處理文件需要將文件讀入內存,修改后,需要寫(xiě)回硬盤(pán)。操作系統提供了對文件讀寫(xiě)的基本API,不同操作 系統的接口和實(shí)現是不一樣的,不過(guò),有一些共同的概念。Java封裝了 操作系統的功能,提供了統一的API。
一個(gè)基本常識是:硬盤(pán)的訪(fǎng)問(wèn)延時(shí),相比內存,是很慢的 。操作系統和硬盤(pán)一般是按塊批量傳輸,而不是按字節,以攤銷(xiāo)延時(shí)開(kāi)銷(xiāo),塊 大小一般至少為512字節,即使應用程序只需要文件的一個(gè)字節,操作 系統也會(huì )至少將一個(gè)塊讀進(jìn)來(lái)。一般而言,應盡量減少接觸硬盤(pán),接觸 一次,就一次多做一些事情。對于網(wǎng)絡(luò )請求和其他輸入輸出設備,原則 都是類(lèi)似的。
另一個(gè)基本常識是:一般讀寫(xiě)文件需要兩次數據復制 ,比如讀文件,需要先從硬盤(pán)復制到操作系統內核,再從內核復制到應用程序分配的內存中。操作系統運行所在的環(huán)境和應用程序是不一樣的,操作系統所在的環(huán)境是內核態(tài),應用程序是用戶(hù)態(tài),應用程序調用操作系統的功能,需要兩次環(huán)境的切換,先從用戶(hù)態(tài)切到內核態(tài),再從內核態(tài)切到用 戶(hù)態(tài)。這種用戶(hù)態(tài)/內核態(tài)的切換是有開(kāi)銷(xiāo)的,應盡量減少這種切換。
為了提升文件操作的效率,應用程序經(jīng)常使用一種常見(jiàn)的策略,即使用緩沖區 。讀文件時(shí),即使目前只需要少量?jì)热?,但預知還會(huì )接著(zhù)讀取,就一次讀取比較多的內容,放到讀緩沖區,下次讀取時(shí),如果緩 沖區有,就直接從緩沖區讀,減少訪(fǎng)問(wèn)操作系統和硬盤(pán)。寫(xiě)文件時(shí),先 寫(xiě)到寫(xiě)緩沖區,寫(xiě)緩沖區滿(mǎn)了之后,再一次性調用操作系統寫(xiě)到硬盤(pán)。 不過(guò),需要注意的是,在寫(xiě)結束的時(shí)候,要記住將緩沖區的剩余內容同步到硬盤(pán)。操作系統自身也會(huì )使用緩沖區,不過(guò),應用程序更了解讀寫(xiě)模式,恰當使用往往可以有更高的效率。
操作系統操作文件一般有打開(kāi)和關(guān)閉的概念 。打開(kāi)文件會(huì )在操作系統內核建立一個(gè)有關(guān)該文件的內存結構,這個(gè)結構一般通過(guò)一個(gè)整數索引來(lái)引用,這個(gè)索引一般稱(chēng)為文件描述符 。這個(gè)結構是消耗內存 的,操作系統能同時(shí)打開(kāi)的文件一般也是有限的,在不用文件的時(shí)候, 應該記住關(guān)閉文件 。關(guān)閉文件一般會(huì )同步緩沖區內容到硬盤(pán),并釋放占據的內存結構。
操作系統一般支持一種稱(chēng)為內存映射文件 的高效的隨機讀寫(xiě)大文 件的方法,將文件直接映射到內存,操作內存就是操作文件。在內存映 射文件中,只有訪(fǎng)問(wèn)到的數據才會(huì )被實(shí)際復制到內存,且數據只會(huì )復制 一次,被操作系統以及多個(gè)應用程序共享。
在Java中處理文件有一些基本概念和類(lèi),包括流、裝飾器設計模 式、Reader/Writer、隨機讀寫(xiě)文件、File、NIO、序列化和反序列化,下 面分別介紹。
在Java中(很多其他語(yǔ)言也類(lèi)似),文件一般不是單獨處理的,而是視為輸入輸出(Input/Output,IO)設備的一種。Java使用基本統一的 概念處理所有的IO,包括鍵盤(pán)、顯示終端、網(wǎng)絡(luò )等。
這個(gè)統一的概念是流 ,流有輸入流 和輸出流之分。輸入流就是可以從中獲取數據,輸入流的實(shí)際提供者可以是鍵盤(pán)、文件、網(wǎng)絡(luò )等;輸出流就是可以向其中寫(xiě)入數據,輸出流的實(shí)際目的地可以是顯示終端、 文件、網(wǎng)絡(luò )等。
Java IO的基本類(lèi)大多位于包java.io中。類(lèi)InputStream表示輸入流, OutputStream表示輸出流,而FileInputStream表示文件輸入流, FileOutputStream表示文件輸出流。
有了流的概念,就有了很多面向流的代碼,比如對流做加密、壓縮、計算信息摘要、計算檢驗和等,這些代碼接受的參數和返回結果都 是抽象的流,它們構成了一個(gè)協(xié)作體系,這類(lèi)似于之前介紹的接口概 念、面向接口的編程,以及容器類(lèi)協(xié)作體系。 一些實(shí)際上不是IO的數據源和目的地也轉換為了流,以方便參與這種協(xié)作,比如字節數組,也包裝為了流ByteArrayInputStream和ByteArrayOutputStream。
基本的流按字節讀寫(xiě),沒(méi)有緩沖區,這不方便使用。Java解決這個(gè) 問(wèn)題的方法是使用裝飾器設計模式,引入了很多裝飾類(lèi),對基本的流增 加功能,以方便使用。一般一個(gè)類(lèi)只關(guān)注一個(gè)方面,實(shí)際使用時(shí),經(jīng)常會(huì )需要多個(gè)裝飾類(lèi)。
Java中有很多裝飾類(lèi),有兩個(gè)基類(lèi):過(guò)濾器輸入流FilterInputStream
和過(guò)濾器輸出流FilterOutputStream
。過(guò)濾類(lèi)似于自來(lái)水管道,流入的是 水,流出的也是水,功能不變,或者只是增加功能。它有很多子類(lèi),這 里列舉一些:
1)對流起緩沖裝飾的子類(lèi)是BufferedInputStream和 BufferedOutputStream。
2)可以按8種基本類(lèi)型和字符串對流進(jìn)行讀寫(xiě)的子類(lèi)是 DataInputStream和DataOutput-Stream。
3)可以對流進(jìn)行壓縮和解壓縮的子類(lèi)有GZIPInputStream、 ZipInputStream、GZIPOutput-Stream和ZipOutputStream。
4)可以將基本類(lèi)型、對象輸出為其字符串表示的子類(lèi)有 PrintStream。
眾多的裝飾類(lèi)使得整個(gè)類(lèi)結構變得比較復雜,完成基本的操作也需 要比較多的代碼;其優(yōu)點(diǎn)是非常靈活,在解決某些問(wèn)題時(shí)也很優(yōu)雅。
以InputStream/OutputStream為基類(lèi)的流基本都是以二進(jìn)制形式處理 數據的,不能夠方便地處理文本文件,沒(méi)有編碼的概念,能夠方便地按字符處理文本數據的基類(lèi)是Reader和Writer,它也有很多子類(lèi):
1)讀寫(xiě)文件的子類(lèi)是FileReader和FileWriter。
2)起緩沖裝飾的子類(lèi)是BufferedReader和BufferedWriter。
3)將字符數組包裝為Reader/Writer的子類(lèi)是CharArrayReader和 CharArrayWriter。
4)將字符串包裝為Reader/Writer的子類(lèi)是StringReader和 StringWriter。
5)將InputStream/OutputStream轉換為Reader/Writer的子類(lèi)是 InputStreamReader和OutputStreamWriter。
6)將基本類(lèi)型、對象輸出為其字符串表示的子類(lèi)是PrintWriter。
大部分情況下,使用流或Reader/Writer讀寫(xiě)文件內容,但Java提供 了一個(gè)獨立的可以隨機讀寫(xiě)文件的類(lèi)RandomAccessFile,適用于大小已 知的記錄組成的文件。該類(lèi)在日常應用開(kāi)發(fā)中用得比較少,但在一些系 統程序中用得比較多。
上面介紹的都是操作數據本身,而關(guān)于文件路徑、文件元數據、文 件目錄、臨時(shí)文件、訪(fǎng)問(wèn)權限管理等,Java使用File這個(gè)類(lèi)來(lái)表示。
以上介紹的類(lèi)基本都位于包java.io下,Java還有一個(gè)關(guān)于IO操作的 包java.nio,nio表示New IO,這個(gè)包下同樣包含大量的類(lèi)。
NIO代表一種不同的看待IO的方式,它有緩沖區和通道的概念。 利 用緩沖區和通道往往可以達成和流類(lèi)似的目的,不過(guò),它們更接近操作系統的概念,某些操作的性能也更高。比如,復制文件到網(wǎng)絡(luò ),通道可 以利用操作系統和硬件提供的DMA機制(Direct Memory Access,直接 內存存?。?,不用CPU和應用程序參與,直接將數據從硬盤(pán)復制到網(wǎng)卡。
除了看待方式不同,NIO還支持一些比較底層的功能,如內存映射 文件、文件加鎖、自定義文件系統、非阻塞式IO、異步IO等。
不過(guò),這些功能要么是比較底層,普通應用程序用到得比較少,要 么主要適用于網(wǎng)絡(luò )IO操作,我們大多不會(huì )介紹,只會(huì )介紹內存映射文 件。
簡(jiǎn)單來(lái)說(shuō),序列化就是將內存中的Java對象持久保存到一個(gè)流中, 反序列化就是從流中恢復Java對象到內存。序列化和反序列化主要有兩個(gè)用處:一是對象狀態(tài)持久化,二是網(wǎng)絡(luò )遠程調用,用于傳遞和返回對象。
Java主要通過(guò)接口Serializable和類(lèi) ObjectInputStream/ObjectOutputStream提供對序列化的支持,基本的使用 是比較簡(jiǎn)單的,但也有一些復雜的地方。不過(guò),Java的默認序列化有一 些缺點(diǎn),比如,序列化后的形式比較大、浪費空間,序列化/反序列化 的性能也比較低,更重要的問(wèn)題是,它是Java特有的技術(shù),不能與其他 語(yǔ)言交互。
XML是前幾年最為流行的描述結構性數據的語(yǔ)言和格式,Java對象也可以序列化為XML格式。XML容易閱讀和編輯,且可以方便地與其 他語(yǔ)言進(jìn)行交互。XML強調格式化但比較“笨重”,JSON是近幾年來(lái)逐 漸流行的輕量級的數據交換格式,在很多場(chǎng)合替代了XML,也非常容 易閱讀和編輯。Java對象也可以序列化為JSON格式,且與其他語(yǔ)言進(jìn)行交互。
XML和JSON都是文本格式,人容易閱讀,但占用的空間相對大一 些,在只用于網(wǎng)絡(luò )遠程調用的情況下,有很多流行的、跨語(yǔ)言的、精簡(jiǎn) 且高效的對象序列化機制,如ProtoBuf、Thrift、MessagePack等。其 中,MessagePack是二進(jìn)制形式的JSON,更小更快。
文件看起來(lái)是一件非常簡(jiǎn)單的事情,但實(shí)際卻沒(méi)有那么簡(jiǎn)單,Java 的設計也不是太完美,包含了大量的類(lèi),這使得對于文件的理解變得困 難。為便于理解,我們將采用以下思路在接下來(lái)的章節中進(jìn)行探討。
首先,我們介紹如何處理二進(jìn)制文件,或者將所有文件看作二進(jìn)制,介紹如何操作,對于常見(jiàn)操作,我們會(huì )封裝,提供一些簡(jiǎn)單易用的方法。下一步,我們介紹如何處理文本文件,我們會(huì )考慮編碼、按行處 理等,同樣,對于常見(jiàn)操作,我們會(huì )封裝,提供簡(jiǎn)單易用的方法。接下 來(lái),我們介紹文件本身和目錄操作File類(lèi),我們也會(huì )封裝常見(jiàn)操作。以 上這些內容是文件處理的基本技術(shù),我們會(huì )在本章進(jìn)行討論。
在日常編程中,我們經(jīng)常會(huì )需要處理一些具體類(lèi)型的文件,如屬性 文件、CSV文件、Excel文件、HTML文件和壓縮文件,直接使用字節 流/字符流來(lái)處理一般是很不方便的,往往有一些更為高層的API,關(guān)于 這些,我們下章介紹。此外,下章還會(huì )介紹比較底層的對文件的操作 RandomAccessFile類(lèi)、內存映射文件,以及序列化。文件看上去應該很 簡(jiǎn)單,但實(shí)際卻包含很多內容,讓我們耐住性子,下一節,先從二進(jìn)制 開(kāi)始。
到此這篇關(guān)于Java基礎之文件概述的文章就介紹到這了,更多相關(guān)Java文件概述內容請搜索腳本之家以前的文章或繼續瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng )、來(lái)自本網(wǎng)站內容采集于網(wǎng)絡(luò )互聯(lián)網(wǎng)轉載等其它媒體和分享為主,內容觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如侵犯了原作者的版權,請告知一經(jīng)查實(shí),將立刻刪除涉嫌侵權內容,聯(lián)系我們QQ:712375056,同時(shí)歡迎投稿傳遞力量。
Copyright ? 2009-2022 56dr.com. All Rights Reserved. 特網(wǎng)科技 特網(wǎng)云 版權所有 特網(wǎng)科技 粵ICP備16109289號
域名注冊服務(wù)機構:阿里云計算有限公司(萬(wàn)網(wǎng)) 域名服務(wù)機構:煙臺帝思普網(wǎng)絡(luò )科技有限公司(DNSPod) CDN服務(wù):阿里云計算有限公司 百度云 中國互聯(lián)網(wǎng)舉報中心 增值電信業(yè)務(wù)經(jīng)營(yíng)許可證B2
建議您使用Chrome、Firefox、Edge、IE10及以上版本和360等主流瀏覽器瀏覽本網(wǎng)站