一.java.io.File類
- java.io.File類用于表示文件/目錄
- File只用于表示文件的信息(名稱,大小等),不能用于文件內(nèi)容的訪問
- RandomAccessFile java提供的對文件內(nèi)容的訪問(可以對文件進(jìn)行讀寫),可以訪問文件的任意位置
- 代碼位置
java文件模型
在硬盤上的文件是byte btye btye存儲的,是數(shù)據(jù)的集合
二.RandomAccessFile 類對于文件的讀寫
- 打開文件
有兩種模式 "rw"(讀寫) "r"(只讀)
RandomAccessFile raf = new RandomeAccessFile(file,"rw");
文件指針,打開文件時指針在開頭 pointer = 0; - 寫方法
raf.write(int) 只寫一個字節(jié)(后8位) ,同時指針指向下一個位置,準(zhǔn)備再次寫入 - 讀取文件
int b = raf.read(); 只讀一個字節(jié) - 文件讀寫后一定要關(guān)閉raf.close()
- 代碼位置
IO流(輸入流,輸出流)
三.字節(jié)流
- InputStream 抽象了應(yīng)用程序讀取數(shù)據(jù)的方式
- OutputStream 抽象了應(yīng)用程序?qū)懗鰯?shù)據(jù)的方式
- EOF = End 讀到-1就到文件結(jié)尾
- 輸入流基本方法
int b = in.read();讀取一個字節(jié)無符號填充到int的低八位,前面補(bǔ)0, -1是EOF
in.read(byte[] buf) 讀取數(shù)據(jù)填充到字節(jié)數(shù)組buf中
in.read(byte[] buf, int start, int size) 從輸入流的start開始位置存放size長度的數(shù)據(jù)到buf數(shù)組中; - 輸出流的基本方法
out.write(int b) 寫出一個byte到流,b的低八位
out.write(byte[] buf) 將buf字節(jié)數(shù)組寫入到流
out.write(btye[], int start ,int size) 字節(jié)數(shù)組buf從start開始位置寫size長度的字節(jié)到流 -
FileInputStream 具體實現(xiàn)了在文件上讀取數(shù)據(jù)
Paste_Image.png - FileOutputStream 實現(xiàn)了向文件中寫出byte數(shù)據(jù)的方法
- 代碼位置
四.對流功能的擴(kuò)展,可以更加方便的讀取int,long,z字符等類型的數(shù)據(jù);
其實方式只是封裝了FileInputStream和FileOutputStream的write和read方法,
注意寫入文件的內(nèi)容還是字節(jié)碼
比如:DataOutputStream.writeInt() 實現(xiàn)方式調(diào)用FileOutputStream.write()四次寫入四個字節(jié)而已
- DataOutputStream 寫出數(shù)據(jù)
/**
* 對流功能的擴(kuò)展寫出數(shù)據(jù)(DataOutputStream)
* @throws IOException
*/
public static void dataOut(File file) throws IOException
{
DataOutputStream out = new DataOutputStream(new FileOutputStream(file));
//寫入一個整型10
out.writeInt(10);
//寫入一個整型20
out.writeInt(20);
//寫入一個長整型10
out.writeLong(10l);
//寫入一個布爾true
out.writeBoolean(true);
//寫入一個雙浮點
out.writeDouble(10.5);
//寫入一個UTF-8編碼的字符
out.writeUTF("中國我愛你");
out.close();
}
- DataInputStream 讀取數(shù)據(jù)
/**
* 對流功能的擴(kuò)展讀取數(shù)據(jù)(DataInputStream)
* 注意寫入文件的內(nèi)容還是字節(jié)碼
* @throws IOException
*/
public static void dataInput(File file) throws IOException
{
DataInputStream in = new DataInputStream(new FileInputStream(file));
//讀取一個整形數(shù)據(jù)
int int1 = in.readInt();
//讀取一個整形數(shù)據(jù)
int int2 = in.readInt();
//讀取一個長整型數(shù)據(jù)
long int3 = in.readLong();
//讀取一個boolean數(shù)據(jù)
boolean b = in.readBoolean();
//讀取一個Double類型數(shù)據(jù)
Double d = in.readDouble();
//讀取一個utf8編碼的數(shù)據(jù)
String str1 = in.readUTF();
//以下數(shù)據(jù)結(jié)果:10, 20, 10, true, 10.5, 中國我愛你
System.out.println(int1 + ", " + int2 + ", " + int3 + ", " + b + ", " + d + ", " + str1);
in.close();
}
測試:
File file = new File("/home/lxf/test/test.php");
IOUtil.dataOut(file);
IOUtil.dataInput(file);//輸出:10, 20, 10, true, 10.5, 中國我愛你
五.字節(jié)流緩沖
BufferedInputStream & BufferedOutputStream
這兩個字節(jié)流未IO提供了帶緩沖區(qū)的操作,一般打開文件進(jìn)行寫入或讀取操作時候,都會加上緩沖,這種模式提高了IO的性能;
從應(yīng)用程序中把輸入放入文件,相當(dāng)于將一缸水導(dǎo)入另一個缸中;
- FileOutputStream.write()方法相當(dāng)與一滴一滴的把水"轉(zhuǎn)移"過去
- DataOutputStream.writeXxx()方法會方便一些,一瓢一瓢的把水"轉(zhuǎn)移"
- BufferedOutStream.write()方法更方便一些,先將水,一瓢一瓢的放入桶中,然后在從桶中"轉(zhuǎn)移"到另一個容器中;
- 三種方式copy文件,速度比較:字節(jié)批量讀取 > 帶緩沖方式 > 單個字節(jié)方式
FileIutputStream.read(buf,0,buf.length) > BufferedOutStream.read() > FileIutputStream.read()
五.字符流
java中的文本(char) : 是16位的無符號整數(shù),是字符的unicode編碼( 雙字節(jié)編碼 )
文件: 是byte byte btye....的數(shù)據(jù)序列
文本文件是文本(char)序列按著某種編碼方案(UTF-8, UTF-16be,gbk等)序列化為byte的存儲結(jié)果
兩個抽象類(Reader, Writer)操作的是文本文件;
字符的處理是一次處理一個字符
字符的底層仍然是基本的字節(jié)序列
-
兩個實現(xiàn)類
InputStreamReader 完成byte流解析為char流, 按著編碼解析//原文件讀取 FileInputStream in = new FileInputStream(srcFile); InputStreamReader isr = new InputStreamReader(in, "utf-8");OutStreamWriter 提供char流到byte流, 按著編碼處理
//目標(biāo)文件寫入 FileOutputStream out = new FileOutputStream(destFile); OutputStreamWriter osw = new OutputStreamWriter(out,"utf-8"); FileReader 和 FileWriter 兩個類以對文件直接讀寫
FileReader reader = new FileReader(srcFile);
FileWriter writer = new FileWriter(destFile);
五.字符流的過濾器
- BufferedReader 一次讀一行
//對文件進(jìn)行讀取操作
FileInputStream in = new FileInputStream(srcFile);
InputStreamReader isr = new InputStreamReader(in, "utf-8");
//FileReader isr = new FileReader(srcFile);
BufferedReader br = new BufferedReader(isr);
- BufferedWriter/PrintWriter 一次寫一行
//對文件進(jìn)行寫入操作
FileOutputStream out = new FileOutputStream(destFile);
OutputStreamWriter isr1 = new OutputStreamWriter(out, "utf-8");
BufferedWriter bw = new BufferedWriter(isr1);
或
PrintWriter pw = new PrintWriter(destFile);
六.序列化的基本操作
- 對象的序列化 : 就是將Object轉(zhuǎn)換成byte序列, 反之叫對象的反序列化;
- 序列化流 ( ObjectOutputStream )
- 反序列化流 ( ObjectInputStream )
- 序列化接口 ( Serializable )
對象必須實現(xiàn)序列化接口,才能進(jìn)行序列化 - 代碼位置
七. transient關(guān)鍵字
- transient 關(guān)鍵字標(biāo)識的實體類屬性不會進(jìn)行jvm的默認(rèn)序列化
- 也可以自己完成該元素的序列化
/**
* Students學(xué)生實體類, 實現(xiàn)了Serializable接口,可以被序列化
* @author lxf
*
*/
public class Students implements Serializable {
private int id;
private String uname;
//transient關(guān)鍵字,表明pass屬性不會進(jìn)行jvm的默認(rèn)序列化, 也可以自己完成該元素的序列化
private transient String pass;
/*
* 自己完成被transient關(guān)鍵字修飾的屬性序列化
*/
private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException
{
//把jvm能默認(rèn)序列化的元素進(jìn)行序列化操作
s.defaultWriteObject();
//自己完成pass的序列化
s.writeObject(pass);
}
/*
* 自己完成被transient關(guān)鍵字修飾的屬性反序列化
*/
private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException
{
s.defaultReadObject();
this.pass = (String) s.readObject();
}
八.序列化中子類和父類構(gòu)造函數(shù)的調(diào)用問題
- 一個類實現(xiàn)了序列化接口,那么其子類都可以進(jìn)行序列化
- 對于類對象進(jìn)行反序列化操作時,如果其父類沒有實現(xiàn)序列化接口,而子類自己實現(xiàn)了序列化接口,那么其父類的構(gòu)造函數(shù)會被調(diào)用,
- 對于類對象進(jìn)行反序列化操作時,如果其父類實現(xiàn)序列化接口,二子類沒有實現(xiàn)了序列化接口,那么其父類的構(gòu)造函數(shù)不會被調(diào)用,
class Foo {
public Foo(){
System.out.println("Foo...");
}
}
class Foo1 extends Foo implements Serializable{
public Foo1(){
System.out.println("Foo1...");
}
}
class Foo2 extends Foo1 implements Serializable{
public Foo2(){
System.out.println("Foo2...");
}
}
File file = new File("/home/lxf/test/Foo2");
Foo2 f = new Foo2();
/*
* 將Foo2對象序列化存儲到/home/lxf/test/Foo2
* 控制臺依次輸出:
* Foo...
Foo1...
Foo2...
*/
SerializeDemo.ObjSaveToFile(file, f);
/*
* 將/home/lxf/test/Foo2中的序列化后的內(nèi)容反序列化讀出為對象
* 控制臺依次輸出:
* Foo...
com.lxf.IOStream.Foo2@732768bb
說明:
對于類對象進(jìn)行反序列化操作時,如果其父類沒有實現(xiàn)序列化接口,而子類自己實現(xiàn)了序列化接口,那么其父類的構(gòu)造函數(shù)會被調(diào)用
對于類對象進(jìn)行反序列化操作時,如果其父類實現(xiàn)序列化接口,而子類沒有實現(xiàn)了序列化接口,那么其父類的構(gòu)造函數(shù)不會被調(diào)用
*/
SerializeDemo.seriFileToObj(file);
