Java IO 常見類使用
阿新 • • 發佈:2022-05-19
Java IO 常見類使用
檔案相關
遍歷檔案
File 類可以用於表示檔案和目錄的資訊,但是它不表示檔案的內容。
比如我要遞迴地列出一個目錄下所有檔案:
public static void listAllFiles(File dir) { if (dir == null || !dir.exists()) { return; } if (dir.isFile()) { System.out.println(dir.getName()); return; } for (File file : dir.listFiles()) { listAllFiles(file); } }
建立檔案
建立檔案的方式有很多,可以使用 File
物件、FileOutputStream
、Files
工具類,還可以使用一些封裝好的工具包:
public static void main(String[] args) throws IOException { File file = new File("src/main/resources/myfile.txt"); if (file.createNewFile()) { System.out.println("File has been created."); } else { System.out.println("File already exists."); } } public static void main(String[] args) throws FileNotFoundException, IOException { FileOutputStream fout = null; try { fout = new FileOutputStream("src/main/resources/myfile.txt"); } finally { if (fout != null) { fout.close(); } } } // 使用 Files 來建立,需要搭配 Path 物件 public static void main(String[] args) throws IOException { Path path = Paths.get("src/main/resources/myfile.txt"); try { Files.createFile(path); } catch (FileAlreadyExistsException ex) { System.err.println("File already exists"); } }
位元組流相關
public static void copyFile(String src, String dist) throws IOException { FileInputStream in = new FileInputStream(src); FileOutputStream out = new FileOutputStream(dist); byte[] buffer = new byte[20 * 1024]; // read() 最多讀取 buffer.length 個位元組 // 返回的是實際讀取的個數 // 返回 -1 的時候表示讀到 eof,即檔案尾 while (in.read(buffer, 0, buffer.length) != -1) { out.write(buffer); } in.close(); out.close(); }
逐行輸出文字檔案的內容
public static void readFileContent(String filePath) throws IOException {
FileReader fileReader = new FileReader(filePath);
BufferedReader bufferedReader = new BufferedReader(fileReader);
String line;
while ((line = bufferedReader.readLine()) != null) {
System.out.println(line);
}
// 裝飾者模式使得 BufferedReader 組合了一個 Reader 物件
// 在呼叫 BufferedReader 的 close() 方法時會去呼叫 Reader 的 close() 方法
// 因此只要一個 close() 呼叫即可
bufferedReader.close();
}
序列化 & Serializable & transient
序列化就是將一個物件轉換成位元組序列,方便儲存和傳輸。
- 序列化: ObjectOutputStream.writeObject()
- 反序列化: ObjectInputStream.readObject()
不會對靜態變數進行序列化,因為序列化只是儲存物件的狀態,靜態變數屬於類的狀態。
序列化的類需要實現 Serializable 介面,它只是一個標準,沒有任何方法需要實現,但是如果不去實現它的話而進行序列化,會丟擲異常。
Serializable
public static void main(String[] args) throws IOException, ClassNotFoundException {
A a1 = new A(123, "abc");
String objectFile = "file/a1";
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream(objectFile));
objectOutputStream.writeObject(a1);
objectOutputStream.close();
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(objectFile));
A a2 = (A) objectInputStream.readObject();
objectInputStream.close();
System.out.println(a2);
}
private static class A implements Serializable {
private static final long serialVersionUID = 1L;
private int x;
private String y;
A(int x, String y) {
this.x = x;
this.y = y;
}
@Override
public String toString() {
return "x = " + x + " " + "y = " + y;
}
}
serialVersionUID
在 序列化儲存/反序列化讀取 或者是 序列化傳輸/反序列化接收 時,JVM 會把傳來的位元組流中的serialVersionUID與本地相應實體(類)的serialVersionUID進行比較,如果相同就認為是一致的,可以進行反序列化,否則就會出現序列化版本不一致的異常。
在對實體類進行不影響業務流程的升級時,比如只追加了一個附加資訊欄位,可以不改變序列化版本號,來實現新舊實體類的相容性(接收方的類裡沒有的欄位被捨棄;多出來的欄位賦初始值)。
transient
ArrayList 中儲存資料的陣列 elementData 是用 transient 修飾的,因為這個陣列是動態擴充套件的,並不是所有的空間都被使用,因此就不需要所有的內容都被序列化。通過重寫序列化和反序列化方法,使得可以只序列化陣列中有內容的那部分資料。
private transient Object[] elementData;