File類
- ?java.io
操作文件和目錄,與平臺無關。具體的常用實例方法:
File file = new File("."); // 以當前路徑創建名為 "." 的 File 對象
? · ? 文件目錄信息函數
? ? - ? String getName/Path/Parent(): 文件名/路徑/父目錄
? ? - ? boolean renameTo(File newName):文件/目錄重命名
? ? - ? long length():文件內容長度
? ? - ? long lastModified():文件最后編輯時間
? · ? 文件檢測函數
? ? - ? boolean exists():判斷文件/目錄是否存在
? ? - ? boolean isFile/isDirectory():判斷是否為文件/目錄
? ? - ? boolean canRead/Write():是否可讀/寫
? ? - ? boolean isAbsolute():文件/目錄是否絕對路徑
? · ? 文件目錄操作函數
? ? - ? boolean creatNewFile():新建 File 對象對應的文件
? ? - ? boolean mkdir():創建 File 對象對應的目錄
? ? - ? boolean delete():刪除文件/目錄
? ? - ? void deleteOnExit():JVM 退出時,刪除文件/目錄
? ? - ? String[] list():返回 File 對象的所有子文件名和路徑名
? ? - ? File[] listFiles():返回 File 對象的所有子文件和路徑
? · ? 文件過濾器
利用File類的String[] list(FilenameFilter filter)方法,過濾得到指定類型的文件/目錄,必須重寫accept方法。具體應用步驟:
? ζ ? 實現FilenameFilter接口;
? ζ ? 實現boolean accept(File dir, String name)方法;
由于FilenameFilter是函數式接口,Lambda表達式可直接作為入參。
?參考 :FilenameFilter 介紹;
? · ? RandomAccessFile類
? Java輸入-輸出體系中功能最豐富的文件內容訪問類(局限性是只能讀寫文件,不能讀寫IO流),提供"隨機訪問"方式,支持追加文件內容、自由定義記錄指針位置:
? - ?long getFilePointer():返回文件記錄指針當前位置;
? - ?void seek(long pos):文件記錄指針定位到pos處;
注意,定點插入數據需要先緩存插入點之后的數據,然后追加新數據,最后還原緩存的數據。RandomAccessFile類可以實現多線程斷點下載/傳輸工具。
Files類
- ?java.io.file
File類的工具類,高度封裝,支持文件復制、讀寫文件、遍歷文件和子目錄,Java-8支持Stream API操作文件目錄和文件內容。
?·???文件復制
Files.copy(Path source, Path target, CopyOption options); // 文件到文件
Files.copy(InputStream in, Path target, CopyOption options); // 輸入流到文件
Files.copy(Path source, OutputStream out); // 文件到輸出流
?·?? 讀寫文件
Files.write(Path src, List<string> strList); // 將字符串內容寫入文件
Files.list(Path path); // 列出path目錄下的所有文件和子目錄
Files.lines(Path src); // 列出文件中所有行
?·?? 遍歷文件和目錄
// 遍歷startPath路徑下所有文件和子目錄,并會“觸發”FileVisitor中的相應方法
Files.walkFileTree(Path startPath, FileVisitor<? super Path> visitor);
Files.walkFileTree(Path startPath, Set<File VisitOption> options, int maxDepth, FileVisitor<? super Path> visitor);
I/O 流
流(stream)是從起源(source)到接收(sink)的有序數據,允許Java程序以相同的方式訪問不同的輸入/輸出源。Java通過裝飾器模式將底層節點流(低級流)封裝成上層處理流(高級流),統一對不同數據源的訪問,靈活方便、執行效率高。利用文件過濾器和I/O流可以實現文件的條件復制。流模型的功能體現:
? · 性能提高:以增加緩沖的方式提高I/O效率;
? · 操作便捷:提供不同的流處理方法,靈活性;
Java-I/O的4個抽象基類:
? · ? 輸入流: InputStream,字節流 - Reader,字符流,
??ζ ?int read():讀取單字節/單字符,返回int型字節/字符數據;
??ζ ?int read(byte/char[] b): 字節/字符數組;
??ζ ?int read(byte/char[] b, int pos, int len):字節/字符數組;
? · ? 輸出流:OutputStream,字節流 - Writer,字符流
??ζ ?void write(int v):將字節/字符數據v寫入到輸出流中;
??ζ ?int write(byte/char[] b)-(String str):字節/字符數組 - 字符串;
??ζ ?int write(byte/char[] b, int pos, int len)-(String str, int pos, int len):字節/字符數組 - 字符串;
字節流比字符流適應范圍廣,但字符流操作方便,文本文件推薦字符流,二進制文件推薦字節流。流的處理依靠隱式的記錄指針:
?? ζ ?void mark(int pos):標記記錄指針當前位置;
?? ζ ?void reset():記錄指針復位;
?? ζ ?long skip(long n):記錄指針前移n個字節/字符;
節點流直接以物理IO節點為構造器參數,處理流以已存在的流為構造器參數。System.out是輸出處理流PrintStream的實例,System.in是輸入節點流InputStream的實例。
? ? 其他的流
? [1].轉換流:InputStreamReader/OutputStreamWriter
處理流,將字節流單向轉換為字符流。
? [2].推回輸入流:PushbackInputStream/Reader
處理流,利用推回緩沖區,其方法unread()可以重復讀取剛剛讀取的內容。
? [3].緩沖流:BufferedInput/OutputStream-BufferedReader/Writer
處理流,結合flush()方法實現緩沖功能。其方法readLine()用于讀取行。
? [4].對象流:ObjectInput/OutputStream
處理流,實現對象的序列化。
? [5].管道流:PipedInput/OutputStream-PipedReader/Writer
節點流,實現進程間通信。
其他的如處理文件、數組、字符串的流均為節點流。
? ? 標準流重定向:將System.in/out重定向到相應位置;
? ?static void setIn/Out/Err(InputStream in/PrintStream out/PrintStream err);
?此外,Runtime.getRuntime().exec("文件名")啟動子進程,JVM可以利用返回的Process對象讀寫子進程的數據。
參考:Java - IO整理
對象序列化機制
允許把內存中的Java對象(對象的類名、實例變量)轉換為平臺無關的二進制字節流(序列化,Serialize),用于永久保存對象到磁盤或利用套接字/RMI傳輸對象,后續可以恢復出Java對象(反序列化,Deserialize)。其中,反序列化讀取的是類對象的數據而不是類本身,必須提供該對象的class文件。對象序列化機制是Java提供分布式網絡編程的基礎,也是Java EE的基礎。
對象支持序列化,其類必須是可序列化的,即必須實現接口之一:
·?Serializable:標記聲明性接口,常用;
·?Externalizable:用于完全自定義序列化機制,性能略優但編程復雜度高;


1 public class MyClass implements java.io.Serializable{ 2 ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("文件名")); 3 MyClass objMy = new MyClass(); out.writeObject(objMy); 4 out.close(); 5 6 ObjectInputStream in = new ObjectInputStream(new FileInputStream("文件名")); 7 MyClass resMy = (MyClass)in.readObject(); 8 in.close(); 9 }
Java序列化機制采用對對象序列化編號的方法避免同一對象重復序列化,此方法中要注意可變對象。
? · ? 自定義序列化機制
?自定義序列化控制程序如何序列化實例變量,重寫如下方法:
·? private void writeObject(ObjectOutputStream out):寫入特定類的實例狀態;
·? private void readObject(ObjectInputStream in):從流中讀取并恢復對象的實例變量;
·? private void readObjectNoData():可以正確初始化反序列化的對象;
關鍵字transient用于修飾實例變量,序列化對象時忽略之,static變量也不會序列化,但是可以通過重寫writeObject()和readObject()手動序列化保存。


1 @override 2 private void writeObject(ObjectOutputStream out) throws IOException{ 3 out.defaultWriteObject(); 4 out.writeXxx(基本類型變量)/writeObject(引用類型變量); 5 } 6 @override 7 private void readObject(ObjectInputStream in) throws IOException,ClassNotFoundException{ 8 in.defaultReadObject(); 9 in.ReadXxx()/readObject(); 10 }
?自定義序列化機制可以加密提供安全性:
·? private Object writeReplace()
序列化對象objA時將對象objA替換成其他對象objB,然后調用writeObject()方法序列化對象objB,可繼承;
·? private Object readResolve()
實現保護性復制整個對象,在readObject()之后調用,返回值會代替readObject()反序列化出來的對象以保證反序列化的正確性,常用于單例類、枚舉類的序列化,可繼承;
? · ? 完全自定義序列化機制
允許完全由程序員自主決定存儲和恢復對象數據,必須實現接口Externalizable和如下方法:
·? public void writeExternal(ObjectOutput out):保存對象的狀態;
·? public void readExternal(ObjectInput in):實現對象反序列化;
方法實現體中,調用DataIn/Output(ObjectIn/Output的父接口)的方法保存/恢復基本類型的實例變量,調用ObjectIn/Output的read/writeObject()方法保存/恢復引用類型的實例變量。


1 public class MyClass implements Externalizable{ 2 public MyClass(){} // 無參的public構造函數 3 @override 4 public void writeExternal(ObjectOutput out) throws IOException{ 5 ... 6 } 7 @override 8 public void readExternal(ObjectInput in) throws IOException,ClassNotFoundException{ 9 ... 10 } 11 }
? · ? 序列化機制版本
Java序列化機制允許為序列化類提供private static final long serialVersionUID標識Java類的序列化版本,保證序列化版本的兼容性、有利于程序在不同JVM間的可移植性。
參考:
- Java對象序列化; 理解Java對象序列化; JAVA序列化機制;序列化介紹;
- Java序列化格式詳解;?
NIO
Java的NIO參見:Java - NIO - sqh;