java中的IO操作總結(四)


前面已經把java io的主要操作講完了

這一節我們來說說關於java io的其他內容

 

Serializable序列化

實例1:對象的序列化

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.Serializable;

@SuppressWarnings("serial")
//一個類要想實現序列化則必須實現Serializable接口
class Person implements Serializable {
	private String name;
	private int age;
	
	public Person(String name, int age) {
		this.name = name;
		this.age = age;
	}
	
	public String toString() {
		return "Name:" + this.name + ", Age:" + this.age;
	}
}

public class Demo {
	public static void main(String[] args) {
		String path = File.separator + "home" + File.separator + "siu" + 
					  File.separator + "work" + File.separator + "demo.txt";
		
		Person p1 = new Person("zhangsan",12);
		Person p2 = new Person("lisi",14);
		
		//此處創建文件寫入流的引用是要給ObjectOutputStream的構造函數玩兒
		FileOutputStream fos = null;
		ObjectOutputStream oos = null;
		try {
			fos = new FileOutputStream(path);
			oos = new ObjectOutputStream(fos);
			
			//這里可以寫入對象,也可以寫入其他類型數據
			oos.writeObject(p1);
			oos.writeObject(p2);
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				oos.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}

所謂對象序列化就是把一個對象進行持久化存儲,方便保留其屬性

通俗點說,等於把一個對象從堆內存里邊揪出來放到硬盤上

當然,如果你開心,你可以序列化其他東西,包括數組,基本數據類型等等

來看看內容,神馬玩意兒這是……

 

實例2:對象的反序列化

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;

public class Demo {
	public static void main(String[] args) {
		String path = File.separator + "home" + File.separator + "siu" + 
					  File.separator + "work" + File.separator + "demo.txt";
		
		//好吧,這里代碼寫得着實有點長了,還要拋異常什么的
		//如果你也看的煩,那就在主方法上拋吧,構造方法里用匿名對象就好了
		//什么?別告訴我你不知道匿名對象
		FileInputStream fis = null;
		ObjectInputStream ois = null;
		try {
			fis = new FileInputStream(path);
			ois = new ObjectInputStream(fis);
			
			//這里返回的其實是一個Object類對象
			//因為我們已知它是個Person類對象
			//所以,就地把它給向下轉型了
			Person p = (Person)ois.readObject();
			System.out.println(p);
			
			//拋死你,煩煩煩~!!!
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} finally {
			try {
				//還是要記得關閉下流
				ois.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}

你看,我們把一個對象存放在硬盤上是為了方便日后使用

現在用得着它了,自然得拿出來

 

管道流

實例3:線程的通信

import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;

//實現Runnable接口,實現一個讀的線程
class Read implements Runnable {
	private PipedInputStream in;
	//將需要讀的管道流傳入到構造函數中
	public Read(PipedInputStream in) {
		this.in = in;
	}
	
	//實現讀這一線程
	public void run() {
		try {
			byte[] buf = new byte[1024];
			int temp = 0;
			//循環讀取
			//read是一個阻塞方法,需要拋異常
			//此處把打印流的代碼也加入進來
			//是因為如果沒有讀取到數據,那么打印的代碼也無效
			while((temp = in.read(buf)) != -1) {
				String str = new String(buf,0,temp);
				System.out.println(str);
			}
		} catch (IOException e) {
			//其實這里應拋出一個自定義異常的
			//暫時我還沒弄清楚
			e.printStackTrace();
		} finally {
			try {
				//我已經拋火了,這只是為了提醒自己異常很重要
				in.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}	
}

//這里實現一個寫的類
class Write implements Runnable {
	private PipedOutputStream out;
	//將管道輸入流傳進來
	public Write(PipedOutputStream out) {
		this.out = out;
	}

	public void run() {
		try {
			//這里開始寫出數據
			out.write("管道輸出".getBytes());
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				//其實應該可以把這個關閉方法寫到上面那個try里邊
				//但是這樣感覺怪怪的,邏輯不大對
				out.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}

public class Demo {
	public static void main(String[] args) {
		PipedInputStream in = new PipedInputStream();
		PipedOutputStream out = new PipedOutputStream();
		try {
			//連接管道
			in.connect(out);
			
			//創建對象,開啟線程
			//此處同樣放進try...catch里面
			//因為如果沒有鏈接管道,下面操作無意義
			Read r = new Read(in);
			Write w = new Write(out);
			//把已經實現好run方法的對象放入線程中執行
			new Thread(r).start();
			new Thread(w).start();
			
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

 好吧,廢了那么大勁兒,就打印了這么一句話,異常拋棄來很煩,為了注重細節……

管道流也許很難理解,其實非也

我們知道,字節流和字符流都需要數組來進行流的中轉

而管道流則直接串聯兩條流,一邊發送數據,一邊接收

然而,同時通信的的兩種狀態,如何才能確定發送和接收的一致性呢

那么,就需要用到線程,無論是接收方還是發送方先執行

總會造成一個線程的阻塞狀態,從而等待另一方的數據傳過來

總體而言,管道流的目的,也就是為了線程通信

此外,還有PipedReader和PipedWriter類,操作原理都一樣,這里就不再贅述了

 

DataOutputStream和DataInputStream類

實例4:基本數據類型的寫入

import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

public class Demo {
	public static void main(String[] args) {
		String path = File.separator + "home" + File.separator + "siu" +
					  File.separator + "work" + File.separator + "demo.txt";
		
		DataOutputStream d = null;
			try {
				//此處需要傳入一個OutputStream類的對象
				d = new DataOutputStream(new FileOutputStream(path));
				//開始寫入基本數據類型
				d.writeInt(12);
				d.writeBoolean(true);
				d.writeDouble(12.2223);
				d.writeChar(97);
				//刷新流
				d.flush();
	
			} catch (IOException e) {
				e.printStackTrace();
			} finally {
				try {
					d.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
	}
}

此處我們並不能直觀看懂內容,因為它采用字節流的方式操作,而不是字符流

我們只需要知道,此程序已經將基本數據類型寫入到硬盤即可

 

實例5:基本數據類型的讀取

import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

public class Demo {
	public static void main(String[] args) {
		String path = File.separator + "home" + File.separator + "siu" +
					  File.separator + "work" + File.separator + "demo.txt";
		
		DataInputStream d = null;
			try {
				d = new DataInputStream(new FileInputStream(path));
				//按存儲順序讀取基本數據類型
				System.out.println(d.readInt());
				System.out.println(d.readBoolean());
				System.out.println(d.readDouble());
				System.out.println(d.readChar());
				
			} catch (IOException e) {
				e.printStackTrace();
			} finally {
				try {
					d.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
	}
}

 這里要注意的是,一定要按照寫入順序讀取,否則會發生數據的打印錯誤


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM