I/O操做總結(四))
阿新 • • 發佈:2017-09-11
zab 方法 字符 add i/o spa 我們 ppr bsp
前面已經把java io的主要操作講完了
這一節我們來說說關於java io的其他內容
Serializable序列化
實例1:對象的序列化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
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:對象的反序列化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
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:線程的通信
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
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:基本數據類型的寫入
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
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:基本數據類型的讀取
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
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();
}
}
}
}
|
這裏要註意的是,一定要按照寫入順序讀取,否則會發生數據的打印錯誤
I/O操做總結(四))