輸入/輸出java 文件算法
•什麼是文件?數組 –文件可認爲是相關記錄或放在一塊兒的數據的集合安全 •文件通常存儲在哪裏?網絡
•JAVA程序通常經過什麼去訪問文件屬性? 併發 • JAVA API :java.io.File 類app File類的用法dom
•File類可使用文件路徑字符串來建立File實例,該文件路徑字符串既能夠是絕對路徑,也能夠是相ide 對路徑,默認狀況下,系統老是依據用戶的工做路徑來解釋相對路徑,這個路徑由系統屬工具 性「user.dir」指定,一般也就是運行Java虛擬機時所在的路徑。
•File不能訪問文件內容自己。若是須要訪問文件內容自己,則須要使用輸入/輸出流。
File
import java.io.File; …… File file = new File(args[0]); System.out.println("文件或目錄是否存在:" + file.exists()); System.out.println("是文件嗎:" + file.isFile()); System.out.println("是目錄嗎:" + file.isDirectory()); System.out.println("名稱:" + file .getName()); System.out.println("路徑: " + file.getPath()); System.out.println("絕對路徑: " + file.getAbsolutePath()); System.out.println("最後修改時間:" + file.lastModified()); System.out.println(「文件大小:」 + file.length()+ 「 字節」); ……
文件過濾器
•在File的list方法中能夠接受一個FilenameFilter參數,經過該參數能夠只列出符合條件的文件。
FilenameFilter接口裏包含了一個accept(File dir, String name)方法,該方法將依次對指定File 的全部子目錄、子文件夾進行迭代,若是該方法返回true則list方法會列出該子目錄或者子文件。
流
•流是指一連串流動的字符,是以先進先出方式發送信息的通道 IO流
•Java的IO流是實現輸入/輸出的基礎,它能夠方便地實現數據的輸入/輸出操做,Java中把不一樣的 輸入/輸出源(鍵盤、文件、網絡鏈接等)抽象表述爲「流」(stream),經過流的方式容許Java程序 使用相同的方式來訪問不一樣的輸入/輸出源。stream是從起源(source)到接收(sink)的有序數 據。
•Java把全部傳統的個流類型(類或抽象類)都放在java.io包中,用以實現輸入/輸出功能。
IO流分類
•按照流的流向來分:能夠分爲輸入流和輸出流。 –輸入流:只能從中讀取數據,而不能向其寫出數據。 –輸出流:只能向其寫出數據,而不能從中讀取數據。 •字節流和字符流 •按照流的角色分,能夠分爲節點流和處理流。
IO流的四個基類
•Java把全部設備裏的有序數據抽象成流模型簡化了輸入/輸出的處理。 •Java的IO流共涉及到40多個類,這些類看上去蕪雜而凌亂,但其實是很是規則、並且彼此之間存在很是緊密的聯繫。Java的IO流的40多個類都是從4個抽象基類派生出來的: –InputStream/Reader:全部輸入流的基類,前者是輸入字節流,後者是輸入字符流。 –OutputStream/Writer:全部輸出流的基類,前者是輸出字節流,後者是輸出字符流。
輸入流
•InputStream和Reader是全部輸入流的基類,它們都是兩個抽象類,自己並不能建立實例來執行輸入,但它們將所謂全部輸入流的模板,因此它們的方法是全部輸入流均可使用的方法。它們包含以下三個方法: –int read():從輸入流中讀取單個字節(至關於從圖15.5所示水管中取出一滴水),返回所讀取的字節數據(字節數據可直接轉換爲int類型)。 –int read(byte[]/char[] b):從輸入流中讀取最多b.length個字節的數據,並將其存儲在字節數組b中,返回實際讀取的字節數。 –int read(byte[]/char[] b, int off, int len):從輸入流中讀取最多len字節的數據,並將其存儲在數組 b 中,放入b數組中時,並非從數組起點開始,而是從off位置開始,返回實際讀取的字節數。
輸出流
•OutputStream和Writer也很是類似,它們採用如圖15.6所示的模型來執行輸出,兩個流都提供了以下三個方法: –void write(int c):將指定的字節/字符輸出到輸出流中,其中c既能夠表明字節,也能夠表明字符。 –void write(byte[]/char[] buf):將字節數組/字符數組中的數據輸出到指定輸出流中。 –void write(char[] cbuf, int off, int len):將字節數組/字符數組中從off位置開始,長度爲len的字節/字符輸出到輸出流中。
處理流的用法
•使用處理流來包裝節點流,程序經過處理流來執行輸入/輸出功能,讓節點流與底層的I/O設備、文件交互。 •實際上咱們要識別處理流很是簡單,只要流的構造器參數不是一個物理節點,而是已經已經存在的流,那麼這種流就必定是處理流;而全部節點流都是直接以物理IO節點做爲構造器參數的。 •程序使用處理流很是簡單,一般只須要在建立處理流時傳入一個節點流做爲構造器參數便可,這樣建立的處理流就是包裝了該節點流的處理流。 轉換流
•輸入/輸出流體系裏還提供了2個轉換流,這兩個轉換流用於實現將字節流轉換成字符流,其中 InputStreamReader將字節輸入流轉換成字符輸入流,OutputStreamWriter將字節輸出流轉換 成字符輸出流。
推回輸入流
•在輸入/輸出流體系中,有兩個特殊的流不同凡響,就是PushbackInputStream和PushbackReader,它們都提供了以下三個方法: –void unread(byte[]/char[] buf):將一個字節/字符數組內容的推回到推回緩衝區裏,從而容許重複讀取剛剛讀取的內容。 –void unread(byte[]/char[] b, int off, int len):將一個字節/字符數組裏從off開始,長度爲len字節/字符的內容推回到推回緩衝區裏,從而容許重複讀取剛剛讀取的內容。 –void unread(int b) :將一個字節/字符的推回到推回緩衝區裏,從而容許重複讀取剛剛讀取的內容。
重定向標準輸入/輸出
•System類裏提供了三個重定向標準輸入/輸出的方法: –static void setErr(PrintStream err):重定向 「標準」錯誤輸出流。 –static void setIn(InputStream in):從新分配「標準」輸入流。 –static void setOut(PrintStream out):重定向 「標準」輸出流。
讀寫其餘進程的數據
•用Runtime對象的exec方法能夠運行平臺上的其餘程序,該方法產生一個Process對象,Process對象表明由該Java程序啓動的子進程。 •Process類提供了以下三個方法,用於讓程序和其子進程進行通訊。 –InputStream getErrorStream():獲取子進程的錯誤流。 –InputStream getInputStream():獲取子進程的輸入流。 OutputStream getOutputStream():獲取子進程的輸出流
RandomAccessFile
•RandomAccessFile是Java輸入/輸出流體系中功能最豐富的文件內容訪問類,它提供了衆多的方 法來訪問文件內容,它既能夠讀取文件內容,也能夠向文件輸出數據。與普通的輸入/輸入流不一樣的 是,RandomAccessFile支持「隨機訪問」的方式,程序能夠直接跳轉到文件的任意地方來讀寫數 據。
RandomAccessFile的記錄指針
•RandomAccessFile對象也包含了一個記錄指針,用以標識當前讀寫處的位置,當程序新建立一個 RandomAccessFile對象時,該對象的文件記錄指針位於文件頭(也就是0處),當讀/寫了n個字節 後,文件記錄指針將會向後移動n個字節。除此以外,RandomAccessFile能夠自由移動該記錄指 針,既能夠向前移動,也能夠向後移動。RandomAccessFile包含了以下兩個方法來操做文件記錄指 針: –long getFilePointer():返回文件記錄指針的當前位置。 –void seek(long pos):將文件記錄指針定位到pos位置。
RandomAccessFile的讀寫模式
•RandomAccessFile類有兩個構造器,其實這兩個構造器基本相同,只是指定文件的形式不一樣而 已:一個使用String參數來指定文件名,一個使用File參數來指定文件自己。除此以外,建立 RandomAccessFile對象時還須要指定一個mode參數,該參數指定RandomAccessFile的訪問模 式,該參數有以下四個值:
–"r":以只讀方式打開指定文件。若是試圖對該RandomAccessFile執行寫入方法都將會拋出 IOException。 –"rw":以讀取、寫入方式打開指定文件。若是該文件尚不存在,則嘗試建立該文件。 –"rws":以讀取、寫入方式打開指定文件。相對於對於 "rw"模式,還要求對文件的內容或元數據的每一個更新都同步寫入到底層存儲設備。 –"rwd":以讀取、寫入方式打開指定文件。對於 "rw",還要求對文件內容的每一個更新都同步寫入到底層存儲設備。
使用RandomAccessFile插入文件
•RandomAccessFile依然不能向文件的指定位置插入內容,若是直接將文件記錄指針移動到中間某 位置後開始輸出,則新輸出的內容會覆蓋文件中原有的內容。
•若是須要向指定位置插入內容,程序須要先把插入點後面內容讀入緩衝區,等將須要插入的數據寫入 文件後,再將緩衝區的內容追加到文件後面。
java.io包
•文本文件的讀寫 –用FileInputStream讀文件 –用FileOutputStream寫文件 –用BufferedReader讀文本文件 –用BufferedWriter寫文本文件 •二進制文件的讀寫 –DataOutputStream –DataInputStream
序列化
•序列化機制容許將實現序列化的Java對象轉換爲字節序列,這些字節序列能夠被保存在磁盤上,或經過網絡傳輸,以備之後從新恢復成原來的對象。序列化機制使得對象能夠脫離程序的運行而獨立存在。 •對象的序列化(Serialize)指將一個Java對象寫入IO流中,與此對應的是,對象的反序列化(Deserialize)則指從IO流中恢復該Java對象。 •若是須要讓某個對象能夠支持序列化機制,必須讓它的類是可序列化的(serializable),爲了讓某個類是可序列化的,該類必須實現以下兩個接口之一: –Serializable –Externalizable
使用Serializable實現序列化
•一旦某個類實現了Serializable接口,則該類的對象就是可序列化的,程序能夠經過以下兩個步驟來序列化該對象。 –(1)建立一個ObjectOutputStream,這個輸出流是一個處理流,因此必須創建在其餘節點流的基礎之上。 –(2)調用ObjectOutputStream對象的writeObject方法輸出可序列化對象。
反序列化的步驟
•(1)建立一個ObjectInputStream,這個輸入流是一個處理流,因此必須創建在其餘節點流的基礎之上。 •(2)調用ObjectInputStream對象的readObject對象讀取流中的對象,該方法返回一個Object類型的Java對象,若是程序知道該Java對象的類型,則能夠將該對象強制類型轉換成其真實的類型。 反序列化時的父類
•當程序建立子類實例時,系統會隱式地爲它的全部父類都建立實例(並創建和此子類實例的關聯)! 當咱們反序列化某個子類的實例時,反序列化機制須要恢復其關聯的父類實例,恢復這些父類實例有兩 種方式: –使用反序列化機制。 –使用父類無參數的構造器。 •若是某個父類既不可序列化,即不能使用第一種機制;也沒有提供無參數的構造器,則不可採用第二 種機制,則反序列化該子類實例將拋出異常。
對象引用的序列化
•若是某個類的屬性類型不是基本類型或String類型,而是另外一個引用類型,那麼這個引用類必須是可序列化的,不然擁有該類型屬性的類是不可序列的。 •Java序列化機制採用了一種特殊的序列化算法,其算法內容是: –全部保存到磁盤中的對象都有一個序列化編號。 –當程序試圖序列化一個對象時,程序將先檢查該對象是否已經被序列化過,只有當該對象從未(在本次虛擬機中)被序列化過,系統纔會將該對象轉換成字節序列並輸出。 –若是某個對象是已經序列化過的,程序將直接只是輸出一個序列化編號,而不是再次從新序列化該對象。
序列化機制可能引發的問題
•因爲Java序列化機制使然:若是屢次序列同一個Java對象時,只有第一次序列化時纔會把該Java對 象轉換成字節序列並輸出,這樣可能引發一個潛在的問題:當程序序列化一個可變對象時,程序只有在 第一次使用writeObject方法輸出時纔會將該對象轉換成字節序列並輸出,即便後面該對象的屬性已 被改變,當程序再次調用writeObject方法時,程序只是輸出前面的序列化編號,因此改變的的屬性 值不會被輸出。
•只有當第一次調用wirteObject方法來輸出對象時纔會將對象轉換成字節序列,並寫出到 ObjectOutputStream;在後面程序中若是該對象的屬性發生了改變,即再次調用writeObject方 法輸出該對象時,改變後的屬性不會被輸出。
自定義序列化
•在屬性前面加上transient關鍵字,能夠指定Java序列化時無需理會該屬性值。 •在序列化和反序列化過程當中須要特殊處理的類應該提供以下特殊簽名的方法,這些特殊的方法用以實現自定義序列化: –private void writeObject(java.io.ObjectOutputStream out)throws IOException –private void readObject(java.io.ObjectInputStream in) – throws IOException, ClassNotFoundException; –private void readObjectNoData()throws ObjectStreamException;
實現Externalizable接口
•該接口裏定義了2個方法: –void readExternal(ObjectInput in):須要序列化的類實現 readExternal方法來實現反序列 化。該方法調用DataInput(它是ObjectInput的父接口)的方法來恢復基本類型的屬性值,調用 ObjectInput的readObject方法來來恢復引用類型的屬性值。
–void writeExternal(ObjectOutput out):須要序列化的類實現writeExternal方法來保存對象 的狀態。該方法調用DataInput(它是ObjectInput的父接口)的方法來保存基本類型的屬性值,調 用 ObjectOutput的writeObject方法來保存引用類型的屬性值。
•實際上採用實現Externalizable接口方式的序列化與前面介紹的自定義序列化很是像,只是 Externalizable接口強制自定義序列化。
序列化時的版本
•Java序列化機制容許爲序列化類提供一個private static final的serialVersionUID屬性值,該屬 性值用於標識該Java類的序列化版本,也就是說若是一個類升級後只要它的serialVersionUID屬性 值保持不變,序列化機制也會把它們當成同一個序列化版本。
Java新IO
•新IO和傳統的IO有相同的目的,都是用於進行輸入/輸出功能,但新IO使用了不一樣的方式來處理處 理輸入/輸出,新IO採用內存映射文件的方式來處理輸入/輸出,新IO將文件或文件的一段區域映射到 內存中,這樣就能夠像訪問內存同樣來訪問文件了(這種方式模擬了操做系統上的虛擬內存的概念), 經過這種方式來進行輸入/輸出比傳統的輸入/輸出要快得多。 •Java中NIO相關的包以下: –java.nio包:主要提供了一些和Buffer相關的類。 –java.nio.channels包:主要包括Channel和Selector相關的類。 –java.nio.charset包:主要包含和字符集相關的類。 –java.nio.channels.spi包:主要包含提供Channel服務的類。 –java.nio.charset.spi包:主要包含提供字符集服務的相關類。
Java新IO的核心概念
•Channel(通道)和Buffer(緩衝)是新IO中的兩個核心對象,Channel是對傳統輸入/輸出系統 中裏的模擬,在新IO系統中全部數據都須要經過通道傳輸;Channel與傳統的InputStream、 OutputStream最大的區別在於它提供了一個map方法,經過該map方法能夠直接將「一塊數據」映 射到內存中。若是說傳統的輸入/輸出系統是面向流的處理,而新IO則是面向塊的處理。
•Buffer能夠被理解成一個容器,它的本質是一個數組,發送到Channel中的全部對象都必須首先放 到Buffer中,而從Channel中讀取的數據也必須先讀到Buffer中。此處的Buffer有點相似於前面我 們介紹的「竹筒」,但該Buffer既能夠像前面那樣一次、一次去Channel中取水,也容許使用 Channel直接將文件的某塊數據映射成Buffer。
•除了Channel和Buffer以外,新IO還提供了用於將UNICODE字符串映射成字節序列以及逆映射操 做的Charset類,還提供了用於支持非阻塞式輸入/輸出的Selector類。
使用Buffer
•從內部結構上來看,Buffer就像一個數組,它能夠保存多個類型相同的數據。Buffer是一個抽象 類,其最經常使用的子類是ByteBuffer,它能夠在底層字節數組上進行get/set操做,除了ByteBuffer 以外,其餘基本數據類型(boolean除外)都有相應的Buffer類:ByteBuffer、CharBuffer、 ShortBuffer、IntBuffer、LongBuffer、FloatBuffer、DoubleBuffer。
Buffer的三個概念
•容量(capacity):緩衝區的 容量(capacity) 表示該Buffer的最大數據容量,即最多能夠存儲 多少數據。緩衝區的容量不可能爲負值,在建立後也不能改變。
•界限(limit):第一個不該該被讀出或者寫入的緩衝區位置索引。也就是說,位於limit後的數據既 不可被讀,也不可被寫。
•位置(position):用於指明下一個能夠被讀出的或者寫入的緩衝區位置索引(相似於IO流中的記 錄指針)。當使用Buffer從Channel中讀取數據時,position的值剛好等於已經讀到了多少數據。當 剛剛新建一個Buffer對象時,其position爲0,若是從Channel中讀取了2個數據到該Buffer中,則 postion爲2,指向Buffer中第三個(第一個位置的索引爲0)位置。
使用Channel
•Channel相似於傳統的流對象,但與傳統的流不一樣的是,Channel有兩個主要的區別: –Channel能夠直接將指定文件的部分或所有映射成Buffer。
–程序不能直接訪問Channel中的數據,包括讀取、寫入都不行,Channel只能與Buffer進行交 互。也就是說,若是要從Channel中取得數據,必須先用Buffer從Channel中取出一些數據,然 後讓程序從Buffer中取出這些數據;若是要將程序中的數據寫入Channel,同樣先讓程序將數據 放入Buffer中,程序再將Buffer裏的輸入寫入Channel中。
Channel及其實現類
•Channel是一個接口,位於java.nio.channels包下,系統爲該接口提供了DatagramChannel、 FileChannel、Pipe.SinkChannel、Pipe.SourceChannel、SelectableChannel、 ServerSocketChannel, SocketChannel等實現類,本節主要介紹FileChannel的用法,根據這 些Channel的名字咱們不難發現新IO裏的Channel是按功能來劃分的,例如Pipe.SinkChannel、 Pipe.SourceChannel用於支持線程之間通訊的管道Channel,而ServerSocketChannel、 SocketChannel則是用於支持TCP網絡通訊的Channel。
編碼集和Charset
•一般而言,把明文的字符串序列轉換成計算機理解的字節序列(二進制文件,普通人看不懂)成爲編 碼,把字節序列轉化成普通人能看懂的明文字符串稱爲解碼。
•粗體字代碼分別實現了將CharBuffer轉換成ByteBuffer,將ByteBuffer轉換成CharBuffer的功 能。實際上Charset裏也提供了以下三個方法: –CharBuffer decode(ByteBuffer bb):將ByteBuffer中字節序列轉換成字符序列的的便捷方法。 –ByteBuffer encode(CharBuffer cb):將CharBuffer中的字符序列轉換成字節序列的便捷方法。 –ByteBuffer encode(String str):將String中的字符序列轉換成字節序列的便捷方法。
文件鎖
•文件鎖在操做系統上是很日常的事情,若是多個運行的程序須要併發修改同一個文件時,須要使用某種機制進行通訊。 •使用文件鎖能夠有效地阻止多條進程併發修改同一份文件,因此如今的大部分操做系統都提供了文件鎖的功能。 •文件鎖控制文件或者文件部分字節的訪問,但文件鎖在不一樣操做系統的差異較大,因此早期的JDK版本並未提供文件鎖的支持。從JDK1.4的新IO開始,Java開始提供文件鎖的支持。 關於文件鎖的注意
•在某些平臺上,文件鎖僅僅是建議性的,並非強制式的。這意味着即便一個程序不能得到文件鎖,它也能夠對該文件進行讀寫。 •在某些平臺上,不能同步地鎖定一個文件並把它映射到內存中。 •文件鎖是由Java虛擬機所持有的,若是兩個Java程序使用同一個Java虛擬機運行,則它們不能對同一個文件進行加鎖。 •在某些平臺上當關閉 FileChannel時,會釋放Java虛擬機在該文件上的全部鎖,所以應該避免對同一個被鎖定的文件打開多個FileChannel。 Java 7新增的文件API
•傳統的Java裏,只有一個File類,即表明文件,又表明目錄。 •Java 7新增了以下API來訪問文件 –Path - 接口,表明一個平臺無關的目錄。提供了大量的方法來操做目錄。 –Paths - 工具類。全部方法都是static的。 –Files - 操做文件的工具類。 •提供了大量的方法來操做文件。 •該類所包含的大量方法可能與咱們平常通常的指望有些出入。
![]() public class FilenameFilterTest { public static void main(String[] args) { File file = new File("."); // 使用Lambda表達式(目標類型爲FilenameFilter)實現文件過濾器。 // 若是文件名以.java結尾,或者文件對應一個路徑,返回true String[] nameList = file.list((dir, name) -> name.endsWith(".java") || new File(name).isDirectory()); for(String name : nameList) { System.out.println(name); } } } ![]() public class FileTest { public static void main(String[] args) throws IOException { // 以當前路徑來建立一個File對象 File file = new File("."); // 直接獲取文件名,輸出一點 System.out.println(file.getName()); // 獲取相對路徑的父路徑可能出錯,下面代碼輸出null System.out.println(file.getParent()); // 獲取絕對路徑 System.out.println(file.getAbsoluteFile()); // 獲取上一級路徑 System.out.println(file.getAbsoluteFile().getParent()); // 在當前路徑下建立一個臨時文件 File tmpFile = File.createTempFile("aaa", ".txt", file); // 指定當JVM退出時刪除該文件 tmpFile.deleteOnExit(); // 以系統當前時間做爲新文件名來建立新文件 File newFile = new File(System.currentTimeMillis() + ""); System.out.println("newFile對象是否存在:" + newFile.exists()); // 以指定newFile對象來建立一個文件 newFile.createNewFile(); // 以newFile對象來建立一個目錄,由於newFile已經存在, // 因此下面方法返回false,即沒法建立該目錄 newFile.mkdir(); // 使用list()方法來列出當前路徑下的全部文件和路徑 String[] fileList = file.list(); System.out.println("====當前路徑下全部文件和路徑以下===="); for (String fileName : fileList) { System.out.println(fileName); } // listRoots()靜態方法列出全部的磁盤根路徑。 File[] roots = File.listRoots(); System.out.println("====系統全部根路徑以下===="); for (File root : roots) { System.out.println(root); } } } ![]() public class FileInputStreamTest { public static void main(String[] args) throws IOException { // 建立字節輸入流 FileInputStream fis = new FileInputStream("FileInputStreamTest.java"); // 建立一個長度爲1024的「竹筒」 byte[] bbuf = new byte[1024]; // 用於保存實際讀取的字節數 int hasRead = 0; // 使用循環來重複「取水」過程 while ((hasRead = fis.read(bbuf)) > 0) { // 取出「竹筒」中水滴(字節),將字節數組轉換成字符串輸入! System.out.print(new String(bbuf, 0, hasRead)); } // 關閉文件輸入流,放在finally塊裏更安全 fis.close(); } } ![]() public class FileOutputStreamTest { public static void main(String[] args) { try ( // 建立字節輸入流 FileInputStream fis = new FileInputStream("FileOutputStreamTest.java"); // 建立字節輸出流 FileOutputStream fos = new FileOutputStream("newFile.txt")) { byte[] bbuf = new byte[32]; int hasRead = 0; // 循環從輸入流中取出數據 while ((hasRead = fis.read(bbuf)) > 0) { // 每讀取一次,即寫入文件輸出流,讀了多少,就寫多少。 fos.write(bbuf, 0, hasRead); } } catch (IOException ioe) { ioe.printStackTrace(); } } } ![]() public class FileReaderTest { public static void main(String[] args) { try ( // 建立字符輸入流 FileReader fr = new FileReader("FileReaderTest.java")) { // 建立一個長度爲32的「竹筒」 char[] cbuf = new char[32]; // 用於保存實際讀取的字符數 int hasRead = 0; // 使用循環來重複「取水」過程 while ((hasRead = fr.read(cbuf)) > 0) { // 取出「竹筒」中水滴(字符),將字符數組轉換成字符串輸入! System.out.print(new String(cbuf, 0, hasRead)); } } catch (IOException ex) { ex.printStackTrace(); } } } ![]() public class FileWriterTest { public static void main(String[] args) { try (FileWriter fw = new FileWriter("poem.txt")) { fw.write("錦瑟 - 李商隱\r\n"); fw.write("錦瑟無故五十弦,一弦一柱思華年。\r\n"); fw.write("莊生曉夢迷蝴蝶,望帝春心託杜鵑。\r\n"); fw.write("滄海月明珠有淚,藍田日暖玉生煙。\r\n"); fw.write("此情可待成追憶,只是當時已惘然。\r\n"); } catch (IOException ioe) { ioe.printStackTrace(); } } } ![]() public class KeyinTest { public static void main(String[] args) { try ( // 將Sytem.in對象轉換成Reader對象 InputStreamReader reader = new InputStreamReader(System.in); // 將普通Reader包裝成BufferedReader BufferedReader br = new BufferedReader(reader)) { String line = null; // 採用循環方式來一行一行的讀取 while ((line = br.readLine()) != null) { // 若是讀取的字符串爲"exit",程序退出 if (line.equals("exit")) { System.exit(1); } // 打印讀取的內容 System.out.println("輸入內容爲:" + line); } } catch (IOException ioe) { ioe.printStackTrace(); } } } ![]() public class PrintStreamTest { public static void main(String[] args) { try (FileOutputStream fos = new FileOutputStream("test.txt"); PrintStream ps = new PrintStream(fos)) { // 使用PrintStream執行輸出 ps.println("普通字符串"); // 直接使用PrintStream輸出對象 ps.println(new PrintStreamTest()); } catch (IOException ioe) { ioe.printStackTrace(); } } } ![]() public class PushbackTest { public static void main(String[] args) { try ( // 建立一個PushbackReader對象,指定推回緩衝區的長度爲64 PushbackReader pr = new PushbackReader(new FileReader( "PushbackTest.java"), 64)) { char[] buf = new char[32]; // 用以保存上次讀取的字符串內容 String lastContent = ""; int hasRead = 0; // 循環讀取文件內容 while ((hasRead = pr.read(buf)) > 0) { // 將讀取的內容轉換成字符串 String content = new String(buf, 0, hasRead); int targetIndex = 0; // 將上次讀取的字符串和本次讀取的字符串拼起來, // 查看是否包含目標字符串, 若是包含目標字符串 if ((targetIndex = (lastContent + content) .indexOf("new PushbackReader")) > 0) { // 將本次內容和上次內容一塊兒推回緩衝區 pr.unread((lastContent + content).toCharArray()); // 從新定義一個長度爲targetIndex的char數組 if (targetIndex > 32) { buf = new char[targetIndex]; } // 再次讀取指定長度的內容(就是目標字符串以前的內容) pr.read(buf, 0, targetIndex); // 打印讀取的內容 System.out.print(new String(buf, 0, targetIndex)); System.exit(0); } else { // 打印上次讀取的內容 System.out.print(lastContent); // 將本次內容設爲上次讀取的內容 lastContent = content; } } } catch (IOException ioe) { ioe.printStackTrace(); } } } ![]() public class StringNodeTest { public static void main(String[] args) { String src = "從明天起,作一個幸福的人\n" + "餵馬,劈柴,周遊世界\n" + "從明天起,關心糧食和蔬菜\n" + "我有一所房子,面朝大海,春暖花開\n" + "從明天起,和每個親人通訊\n" + "告訴他們個人幸福\n"; char[] buffer = new char[32]; int hasRead = 0; try (StringReader sr = new StringReader(src)) { // 採用循環讀取的訪問讀取字符串 while ((hasRead = sr.read(buffer)) > 0) { System.out.print(new String(buffer, 0, hasRead)); } } catch (IOException ioe) { ioe.printStackTrace(); } try ( // 建立StringWriter時,實際上以一個StringBuffer做爲輸出節點 // 下面指定的20就是StringBuffer的初始長度 StringWriter sw = new StringWriter()) { // 調用StringWriter的方法執行輸出 sw.write("有一個美麗的新世界,\n"); sw.write("她在遠方等我,\n"); sw.write("哪裏有天真的孩子,\n"); sw.write("還有姑娘的酒窩\n"); System.out.println("----下面是sw的字符串節點裏的內容----"); // 使用toString()方法返回StringWriter的字符串節點的內容 System.out.println(sw.toString()); } catch (IOException ex) { ex.printStackTrace(); } } } ![]() public class RedirectIn { public static void main(String[] args) { try (FileInputStream fis = new FileInputStream("RedirectIn.java")) { // 將標準輸入重定向到fis輸入流 System.setIn(fis); // 使用System.in建立Scanner對象,用於獲取標準輸入 Scanner sc = new Scanner(System.in); // 增長下面一行將只把回車做爲分隔符 sc.useDelimiter("\n"); // 判斷是否還有下一個輸入項 while (sc.hasNext()) { // 輸出輸入項 System.out.println("鍵盤輸入的內容是:" + sc.next()); } } catch (IOException ex) { ex.printStackTrace(); } } } ![]() public class RedirectOut { public static void main(String[] args) { try ( // 一次性建立PrintStream輸出流 PrintStream ps = new PrintStream(new FileOutputStream("out.txt"))) { // 將標準輸出重定向到ps輸出流 System.setOut(ps); // 向標準輸出輸出一個字符串 System.out.println("普通字符串"); // 向標準輸出輸出一個對象 System.out.println(new RedirectOut()); } catch (IOException ex) { ex.printStackTrace(); } } } ![]() public class ReadFromProcess { public static void main(String[] args) throws IOException { // 運行javac命令,返回運行該命令的子進程 Process p = Runtime.getRuntime().exec("javac"); try ( // 以p進程的錯誤流建立BufferedReader對象 // 這個錯誤流對本程序是輸入流,對p進程則是輸出流 BufferedReader br = new BufferedReader(new InputStreamReader( p.getErrorStream()))) { String buff = null; // 採起循環方式來讀取p進程的錯誤輸出 while ((buff = br.readLine()) != null) { System.out.println(buff); } } } } ![]() public class WriteToProcess { public static void main(String[] args) throws IOException { // 運行java ReadStandard命令,返回運行該命令的子進程 Process p = Runtime.getRuntime().exec("java ReadStandard"); try ( // 以p進程的輸出流建立PrintStream對象 // 這個輸出流對本程序是輸出流,對p進程則是輸入流 PrintStream ps = new PrintStream(p.getOutputStream())) { // 向ReadStandard程序寫入內容,這些內容將被ReadStandard讀取 ps.println("普通字符串"); ps.println(new WriteToProcess()); } } } // 定義一個ReadStandard類,該類能夠接受標準輸入, // 並將標準輸入寫入out.txt文件。 class ReadStandard { public static void main(String[] args) { try ( // 使用System.in建立Scanner對象,用於獲取標準輸入 Scanner sc = new Scanner(System.in); PrintStream ps = new PrintStream( new FileOutputStream("out.txt"))) { // 增長下面一行將只把回車做爲分隔符 sc.useDelimiter("\n"); // 判斷是否還有下一個輸入項 while (sc.hasNext()) { // 輸出輸入項 ps.println("鍵盤輸入的內容是:" + sc.next()); } } catch (IOException ioe) { ioe.printStackTrace(); } } } ![]() public class AppendContent { public static void main(String[] args) { try ( // 以讀、寫方式打開一個RandomAccessFile對象 RandomAccessFile raf = new RandomAccessFile("out.txt", "rw")) { // 將記錄指針移動到out.txt文件的最後 raf.seek(raf.length()); raf.write("追加的內容!\r\n".getBytes()); } catch (IOException ex) { ex.printStackTrace(); } } } ![]() public class InsertContent { public static void insert(String fileName, long pos, String insertContent) throws IOException { File tmp = File.createTempFile("tmp", null); tmp.deleteOnExit(); try (RandomAccessFile raf = new RandomAccessFile(fileName, "rw"); // 使用臨時文件來保存插入點後的數據 FileOutputStream tmpOut = new FileOutputStream(tmp); FileInputStream tmpIn = new FileInputStream(tmp)) { raf.seek(pos); // ------下面代碼將插入點後的內容讀入臨時文件中保存------ byte[] bbuf = new byte[64]; // 用於保存實際讀取的字節數 int hasRead = 0; // 使用循環方式讀取插入點後的數據 while ((hasRead = raf.read(bbuf)) > 0) { // 將讀取的數據寫入臨時文件 tmpOut.write(bbuf, 0, hasRead); } // ----------下面代碼插入內容---------- // 把文件記錄指針從新定位到pos位置 raf.seek(pos); // 追加須要插入的內容 raf.write(insertContent.getBytes()); // 追加臨時文件中的內容 while ((hasRead = tmpIn.read(bbuf)) > 0) { raf.write(bbuf, 0, hasRead); } } } public static void main(String[] args) throws IOException { insert("InsertContent.java", 45, "插入的內容\r\n"); } } ![]() public class RandomAccessFileTest { public static void main(String[] args) { try (RandomAccessFile raf = new RandomAccessFile( "RandomAccessFileTest.java", "r")) { // 獲取RandomAccessFile對象文件指針的位置,初始位置是0 System.out.println("RandomAccessFile的文件指針的初始位置:" + raf.getFilePointer()); // 移動raf的文件記錄指針的位置 raf.seek(300); byte[] bbuf = new byte[1024]; // 用於保存實際讀取的字節數 int hasRead = 0; // 使用循環來重複「取水」過程 while ((hasRead = raf.read(bbuf)) > 0) { // 取出「竹筒」中水滴(字節),將字節數組轉換成字符串輸入! System.out.print(new String(bbuf, 0, hasRead)); } } catch (IOException ex) { ex.printStackTrace(); } } } ![]() public class Person implements java.io.Serializable { private String name; private transient int age; // 注意此處沒有提供無參數的構造器! public Person(String name, int age) { System.out.println("有參數的構造器"); this.name = name; this.age = age; } // 省略name與age的setter和getter方法 // name的setter和getter方法 public void setName(String name) { this.name = name; } public String getName() { return this.name; } // age的setter和getter方法 public void setAge(int age) { this.age = age; } public int getAge() { return this.age; } } ![]() public class TransientTest { public static void main(String[] args) { try ( // 建立一個ObjectOutputStream輸出流 ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream( "transient.txt")); // 建立一個ObjectInputStream輸入流 ObjectInputStream ois = new ObjectInputStream( new FileInputStream("transient.txt"))) { Person per = new Person("孫悟空", 500); // 系統會per對象轉換字節序列並輸出 oos.writeObject(per); Person p = (Person) ois.readObject(); System.out.println(p.getAge()); } catch (Exception ex) { ex.printStackTrace(); } } } ![]() public class Orientation implements java.io.Serializable { public static final Orientation HORIZONTAL = new Orientation(1); public static final Orientation VERTICAL = new Orientation(2); private int value; private Orientation(int value) { this.value = value; } // 爲枚舉類增長readResolve()方法 private Object readResolve() throws ObjectStreamException { if (value == 1) { return HORIZONTAL; } if (value == 2) { return VERTICAL; } return null; } } ![]() public class ResolveTest { public static void main(String[] args) { try ( // 建立一個ObjectOutputStream輸入流 ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream( "transient.txt")); // 建立一個ObjectInputStream輸入流 ObjectInputStream ois = new ObjectInputStream( new FileInputStream("transient.txt"))) { oos.writeObject(Orientation.HORIZONTAL); Orientation ori = (Orientation) ois.readObject(); System.out.println(ori == Orientation.HORIZONTAL); } catch (Exception ex) { ex.printStackTrace(); } } } ![]() public class Person implements java.io.Serializable { private String name; private int age; // 注意此處沒有提供無參數的構造器! public Person(String name, int age) { System.out.println("有參數的構造器"); this.name = name; this.age = age; } // 省略name與age的setter和getter方法 // name的setter和getter方法 public void setName(String name) { this.name = name; } public String getName() { return this.name; } // age的setter和getter方法 public void setAge(int age) { this.age = age; } public int getAge() { return this.age; } // 重寫writeReplace方法,程序在序列化該對象以前,先調用該方法 private Object writeReplace() throws ObjectStreamException { ArrayList<Object> list = new ArrayList<>(); list.add(name); list.add(age); return list; } } ![]() public class ReplaceTest { public static void main(String[] args) { try ( // 建立一個ObjectOutputStream輸出流 ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream( "replace.txt")); // 建立一個ObjectInputStream輸入流 ObjectInputStream ois = new ObjectInputStream( new FileInputStream("replace.txt"))) { Person per = new Person("孫悟空", 500); // 系統將per對象轉換字節序列並輸出 oos.writeObject(per); // 反序列化讀取獲得的是ArrayList ArrayList list = (ArrayList) ois.readObject(); System.out.println(list); } catch (Exception ex) { ex.printStackTrace(); } } } ![]() public class Person implements java.io.Externalizable { private String name; private int age; // 注意此處沒有提供無參數的構造器! public Person(String name, int age) { System.out.println("有參數的構造器"); this.name = name; this.age = age; } // 省略name與age的setter和getter方法 // name的setter和getter方法 public void setName(String name) { this.name = name; } public String getName() { return this.name; } // age的setter和getter方法 public void setAge(int age) { this.age = age; } public int getAge() { return this.age; } public void writeExternal(java.io.ObjectOutput out) throws IOException { // 將name實例變量的值反轉後寫入二進制流 out.writeObject(new StringBuffer(name).reverse()); out.writeInt(age); } public void readExternal(java.io.ObjectInput in) throws IOException, ClassNotFoundException { // 將讀取的字符串反轉後賦給name實例變量 this.name = ((StringBuffer) in.readObject()).reverse().toString(); this.age = in.readInt(); } } ![]() public class Person implements java.io.Serializable { private String name; private int age; // 注意此處沒有提供無參數的構造器! public Person(String name, int age) { System.out.println("有參數的構造器"); this.name = name; this.age = age; } // 省略name與age的setter和getter方法 // name的setter和getter方法 public void setName(String name) { this.name = name; } public String getName() { return this.name; } // age的setter和getter方法 public void setAge(int age) { this.age = age; } public int getAge() { return this.age; } private void writeObject(java.io.ObjectOutputStream out) throws IOException { // 將name實例變量的值反轉後寫入二進制流 out.writeObject(new StringBuffer(name).reverse()); out.writeInt(age); } private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException { // 將讀取的字符串反轉後賦給name實例變量 this.name = ((StringBuffer) in.readObject()).reverse().toString(); this.age = in.readInt(); } } ![]() public class Person implements java.io.Serializable { private String name; private int age; // 注意此處沒有提供無參數的構造器! public Person(String name, int age) { System.out.println("有參數的構造器"); this.name = name; this.age = age; } // 省略name與age的setter和getter方法 // name的setter和getter方法 public void setName(String name) { this.name = name; } public String getName() { return this.name; } // age的setter和getter方法 public void setAge(int age) { this.age = age; } public int getAge() { return this.age; } } ![]() public class ReadObject { public static void main(String[] args) { try ( // 建立一個ObjectInputStream輸入流 ObjectInputStream ois = new ObjectInputStream(new FileInputStream( "object.txt"))) { // 從輸入流中讀取一個Java對象,並將其強制類型轉換爲Person類 Person p = (Person) ois.readObject(); System.out.println("名字爲:" + p.getName() + "\n年齡爲:" + p.getAge()); } catch (Exception ex) { ex.printStackTrace(); } } } ![]() public class ReadTeacher { public static void main(String[] args) { try ( // 建立一個ObjectInputStream輸出流 ObjectInputStream ois = new ObjectInputStream(new FileInputStream( "teacher.txt"))) { // 依次讀取ObjectInputStream輸入流中的四個對象 Teacher t1 = (Teacher) ois.readObject(); Teacher t2 = (Teacher) ois.readObject(); Person p = (Person) ois.readObject(); Teacher t3 = (Teacher) ois.readObject(); // 輸出true System.out.println("t1的student引用和p是否相同:" + (t1.getStudent() == p)); // 輸出true System.out.println("t2的student引用和p是否相同:" + (t2.getStudent() == p)); // 輸出true System.out.println("t2和t3是不是同一個對象:" + (t2 == t3)); } catch (Exception ex) { ex.printStackTrace(); } } } ![]() public class SerializeMutable { public static void main(String[] args) { try ( // 建立一個ObjectOutputStream輸入流 ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream( "mutable.txt")); // 建立一個ObjectInputStream輸入流 ObjectInputStream ois = new ObjectInputStream( new FileInputStream("mutable.txt"))) { Person per = new Person("孫悟空", 500); // 系統會per對象轉換字節序列並輸出 oos.writeObject(per); // 改變per對象的name實例變量 per.setName("豬八戒"); // 系統只是輸出序列化編號,因此改變後的name不會被序列化 oos.writeObject(per); Person p1 = (Person) ois.readObject(); // ① Person p2 = (Person) ois.readObject(); // ② // 下面輸出true,即反序列化後p1等於p2 System.out.println(p1 == p2); // 下面依然看到輸出"孫悟空",即改變後的實例變量沒有被序列化 System.out.println(p2.getName()); } catch (Exception ex) { ex.printStackTrace(); } } } ![]() public class Teacher implements java.io.Serializable { private String name; private Person student; public Teacher(String name, Person student) { this.name = name; this.student = student; } // 此處省略了name和student的setter和getter方法 // name的setter和getter方法 public void setName(String name) { this.name = name; } public String getName() { return this.name; } // student的setter和getter方法 public void setStudent(Person student) { this.student = student; } public Person getStudent() { return this.student; } } ![]() public class WriteObject { public static void main(String[] args) { try ( // 建立一個ObjectOutputStream輸出流 ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream( "object.txt"))) { Person per = new Person("孫悟空", 500); // 將per對象寫入輸出流 oos.writeObject(per); } catch (IOException ex) { ex.printStackTrace(); } } } ![]() public class WriteTeacher { public static void main(String[] args) { try ( // 建立一個ObjectOutputStream輸出流 ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream( "teacher.txt"))) { Person per = new Person("孫悟空", 500); Teacher t1 = new Teacher("唐僧", per); Teacher t2 = new Teacher("菩提祖師", per); // 依次將四個對象寫入輸出流 oos.writeObject(t1); oos.writeObject(t2); oos.writeObject(per); oos.writeObject(t2); } catch (IOException ex) { ex.printStackTrace(); } } } ![]() public class BufferTest { public static void main(String[] args) { // 建立Buffer CharBuffer buff = CharBuffer.allocate(8); // ① System.out.println("capacity: " + buff.capacity()); System.out.println("limit: " + buff.limit()); System.out.println("position: " + buff.position()); // 放入元素 buff.put('a'); buff.put('b'); buff.put('c'); // ② System.out.println("加入三個元素後,position = " + buff.position()); // 調用flip()方法 buff.flip(); // ③ System.out.println("執行flip()後,limit = " + buff.limit()); System.out.println("position = " + buff.position()); // 取出第一個元素 System.out.println("第一個元素(position=0):" + buff.get()); // ④ System.out.println("取出一個元素後,position = " + buff.position()); // 調用clear方法 buff.clear(); // ⑤ System.out.println("執行clear()後,limit = " + buff.limit()); System.out.println("執行clear()後,position = " + buff.position()); System.out.println("執行clear()後,緩衝區內容並無被清除:" + "第三個元素爲:" + buff.get(2)); // ⑥ System.out.println("執行絕對讀取後,position = " + buff.position()); } } ![]() public class CharsetTest { public static void main(String[] args) { // 獲取Java支持的所有字符集 SortedMap<String, Charset> map = Charset.availableCharsets(); for (String alias : map.keySet()) { // 輸出字符集的別名和對應的Charset對象 System.out.println(alias + "----->" + map.get(alias)); } } } ![]() public class CharsetTransform { public static void main(String[] args) throws Exception { // 建立簡體中文對應的Charset Charset cn = Charset.forName("GBK"); // 獲取cn對象對應的編碼器和解碼器 CharsetEncoder cnEncoder = cn.newEncoder(); CharsetDecoder cnDecoder = cn.newDecoder(); // 建立一個CharBuffer對象 CharBuffer cbuff = CharBuffer.allocate(8); cbuff.put('孫'); cbuff.put('悟'); cbuff.put('空'); cbuff.flip(); // 將CharBuffer中的字符序列轉換成字節序列 ByteBuffer bbuff = cnEncoder.encode(cbuff); // 循環訪問ByteBuffer中的每一個字節 for (int i = 0; i < bbuff.capacity(); i++) { System.out.print(bbuff.get(i) + " "); } // 將ByteBuffer的數據解碼成字符序列 System.out.println("\n" + cnDecoder.decode(bbuff)); } } ![]() public class FileChannelTest { public static void main(String[] args) { File f = new File("FileChannelTest.java"); try ( // 建立FileInputStream,以該文件輸入流建立FileChannel FileChannel inChannel = new FileInputStream(f).getChannel(); // 以文件輸出流建立FileBuffer,用以控制輸出 FileChannel outChannel = new FileOutputStream("a.txt") .getChannel()) { // 將FileChannel裏的所有數據映射成ByteBuffer MappedByteBuffer buffer = inChannel.map( FileChannel.MapMode.READ_ONLY, 0, f.length()); // ① // 使用GBK的字符集來建立解碼器 Charset charset = Charset.forName("GBK"); // 直接將buffer裏的數據所有輸出 outChannel.write(buffer); // ② // 再次調用buffer的clear()方法,復原limit、position的位置 buffer.clear(); // 建立解碼器(CharsetDecoder)對象 CharsetDecoder decoder = charset.newDecoder(); // 使用解碼器將ByteBuffer轉換成CharBuffer CharBuffer charBuffer = decoder.decode(buffer); // CharBuffer的toString方法能夠獲取對應的字符串 System.out.println(charBuffer); } catch (IOException ex) { ex.printStackTrace(); } } } ![]() public class FileLockTest { public static void main(String[] args) throws Exception { try ( // 使用FileOutputStream獲取FileChannel FileChannel channel = new FileOutputStream("a.txt").getChannel()) { // 使用非阻塞式方式對指定文件加鎖 FileLock lock = channel.tryLock(); // 程序暫停10s Thread.sleep(10000); // 釋放鎖 lock.release(); } } } ![]() public class RandomFileChannelTest { public static void main(String[] args) throws IOException { File f = new File("a.txt"); try ( // 建立一個RandomAccessFile對象 RandomAccessFile raf = new RandomAccessFile(f, "rw"); // 獲取RandomAccessFile對應的Channel FileChannel randomChannel = raf.getChannel()) { // 將Channel中全部數據映射成ByteBuffer ByteBuffer buffer = randomChannel.map( FileChannel.MapMode.READ_ONLY, 0, f.length()); // 把Channel的記錄指針移動到最後 randomChannel.position(f.length()); // 將buffer中全部數據輸出 randomChannel.write(buffer); } } } ![]() public class ReadFile { public static void main(String[] args) throws IOException { try ( // 建立文件輸入流 FileInputStream fis = new FileInputStream("ReadFile.java"); // 建立一個FileChannel FileChannel fcin = fis.getChannel()) { // 定義一個ByteBuffer對象,用於重複取水 ByteBuffer bbuff = ByteBuffer.allocate(256); // 將FileChannel中數據放入ByteBuffer中 while (fcin.read(bbuff) != -1) { // 鎖定Buffer的空白區 bbuff.flip(); // 建立Charset對象 Charset charset = Charset.forName("GBK"); // 建立解碼器(CharsetDecoder)對象 CharsetDecoder decoder = charset.newDecoder(); // 將ByteBuffer的內容轉碼 CharBuffer cbuff = decoder.decode(bbuff); System.out.print(cbuff); // 將Buffer初始化,爲下一次讀取數據作準備 bbuff.clear(); } } } } ![]() public class FilesTest { public static void main(String[] args) throws Exception { // 複製文件 Files.copy(Paths.get("FilesTest.java") , new FileOutputStream("a.txt")); // 判斷FilesTest.java文件是否爲隱藏文件 System.out.println("FilesTest.java是否爲隱藏文件:" + Files.isHidden(Paths.get("FilesTest.java"))); // 一次性讀取FilesTest.java文件的全部行 List<String> lines = Files.readAllLines(Paths .get("FilesTest.java"), Charset.forName("gbk")); System.out.println(lines); // 判斷指定文件的大小 System.out.println("FilesTest.java的大小爲:" + Files.size(Paths.get("FilesTest.java"))); List<String> poem = new ArrayList<>(); poem.add("水晶潭底銀魚躍"); poem.add("清徐風中碧竿橫"); // 直接將多個字符串內容寫入指定文件中 Files.write(Paths.get("pome.txt") , poem , Charset.forName("gbk")); // 使用Java 8新增的Stream API列出當前目錄下全部文件和子目錄 Files.list(Paths.get(".")).forEach(path -> System.out.println(path)); // 使用Java 8新增的Stream API讀取文件內容 Files.lines(Paths.get("FilesTest.java") , Charset.forName("gbk")) .forEach(line -> System.out.println(line)); FileStore cStore = Files.getFileStore(Paths.get("C:")); // 判斷C盤的總空間,可用空間 System.out.println("C:共有空間:" + cStore.getTotalSpace()); System.out.println("C:可用空間:" + cStore.getUsableSpace()); } } ![]() public class FileVisitorTest { public static void main(String[] args) throws Exception { // 遍歷g:\publish\codes\15目錄下的全部文件和子目錄 Files.walkFileTree(Paths.get("g:", "publish", "codes", "15"), new SimpleFileVisitor<Path>() { // 訪問文件時候觸發該方法 @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { System.out.println("正在訪問" + file + "文件"); // 找到了FileInputStreamTest.java文件 if (file.endsWith("FileInputStreamTest.java")) { System.out.println("--已經找到目標文件--"); return FileVisitResult.TERMINATE; } return FileVisitResult.CONTINUE; } // 開始訪問目錄時觸發該方法 @Override public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { System.out.println("正在訪問:" + dir + " 路徑"); return FileVisitResult.CONTINUE; } }); } } ![]() public class PathTest { public static void main(String[] args) throws Exception { // 以當前路徑來建立Path對象 Path path = Paths.get("."); System.out.println("path裏包含的路徑數量:" + path.getNameCount()); System.out.println("path的根路徑:" + path.getRoot()); // 獲取path對應的絕對路徑。 Path absolutePath = path.toAbsolutePath(); System.out.println(absolutePath); // 獲取絕對路徑的根路徑 System.out.println("absolutePath的根路徑:" + absolutePath.getRoot()); // 獲取絕對路徑所包含的路徑數量 System.out.println("absolutePath裏包含的路徑數量:" + absolutePath.getNameCount()); System.out.println(absolutePath.getName(3)); // 以多個String來構建Path對象 Path path2 = Paths.get("g:", "publish", "codes"); System.out.println(path2); } } ![]() public class WatchServiceTest { public static void main(String[] args) throws Exception { // 獲取文件系統的WatchService對象 WatchService watchService = FileSystems.getDefault().newWatchService(); // 爲C:盤根路徑註冊監聽 Paths.get("C:/").register(watchService, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_MODIFY, StandardWatchEventKinds.ENTRY_DELETE); while (true) { // 獲取下一個文件改動事件 WatchKey key = watchService.take(); // ① for (WatchEvent<?> event : key.pollEvents()) { System.out.println(event.context() + " 文件發生了 " + event.kind() + "事件!"); } // 重設WatchKey boolean valid = key.reset(); // 若是重設失敗,退出監聽 if (!valid) { break; } } } } |