一 .
InputStream 和 OutPutStream 是最基本的兩個最基本的輸入輸出流 其他所有的字節輸入輸出流都是他們的子類。他倆都是抽象類不能夠實例對象。
Reader Writer 是兩個最基本的 字符輸入輸出流 , 他們兩個都是抽象類不能夠實例對象。
二 .
對于輸入輸出流做處理的時候可以單一字節或者單一字符進行處理,也可以選擇 用一個緩沖區做處理。
字節處理的時候需要 byte[] cache=new byte[1024]
字符處理的時候需要 char [] cache=new char[1024]
三 .
當我們對于輸出流以及輸入流做關閉的時候 我們可以選擇使用輸出流 flush()操作代替 關閉流。
四
當我們需要做涉及到文件的復制粘貼 無論什么文件除了字符文件應該都要使用字節流
切記不要使用字符流處理,文件 ,音頻,視頻以及其他類型的文件
五
FileOutputStream(File file, boolean append)
在文件追加的問題 當我們構造對象的時候可以將第二個參數置位true 這時候可以在文件后面追加字節或者字符了。
六 :
BufferedInputStream BufferedOutputStream 這兩個對象在初始化的時候需要在構造函數里面加入輸入輸出流 這些內存的緩存流里面加入了緩存的數組 字節的是 81024 字符的32個字符
所以我們在操作的時候可以省略自定義 緩存流的操作 如果我們自定義加入了緩存流的話 這樣可以更加加快了轉換的速度 。
當我們加入了 內存緩存流的時候 我們在關閉流的時候可以直接通過**********(輸出)**緩存流直接進行強制刷新的操作flush()
這樣的話可以省去 自己關閉輸入輸出流的操作。
BufferedReader 和 BufferedWriter 是對于字符操作的緩存流使用方式和上面一樣。
BufferedReader 里面的方法 readLine //處理數據 如果已到達流末尾,則返回 null
BufferedWriter 里面的方法 write(String s)可以直接寫入字符串
BufferedWriter 里面的方法 newLine 直接在文件里面寫入換行的操作。
BufferedInputStream
BufferedOutputStream
ByteArrayInputStream
ByteArrayOutputStream
轉換流 : 只能是字節轉換成字符
InputStreamReader
OutputStreamWriter
鍵盤錄入就是轉換流的一個實例應用:
Reader reader=new InputStreamReader(System.in);
BufferedReader bufferedReader=new BufferedReader(reader);
標準的輸出流 System.out --->PrintStream
(1)作用:在控制臺輸出各種類型的數據
(2)把System.out.println()把輸出結果放到文件里,不要在控制臺輸出
自己實例化PrintStream new PrintStream(new File(""));
*************println()方法和 write()的方法的比較
ps.write(100); write的方法只有三個 所以此處輸出的是100的阿斯可碼 所以此處輸出的是 d
ps.println(100) 此處輸出的是 100
數據流
- DataInputStream DataOutputStream
- 里面提供了存儲java基本數類型 :四類八種 和 String
- 處理流 只針對字節流(二進制文件)
當我們學習了 對象輸出流之后就會發現 數據輸入輸出流就會被對象輸入輸出流代替了。
數據流的輸入輸出是相互對應的 所以 我們 在read的讀取順序應該按照write時候存儲的順序
7、對象的序列化(serialization)**
(1)何為對象的序列化?
把對象保存到文件里--->對象的序列化
(2)何為反序列化?
把文件里的數據讀取出來形成對象--->反序列化
(3)作用:
a、永久保存數據(持久化)
b、可以在網絡之間傳輸數據
(4)如何實現?
a、ObjectOutputStream:對象輸出流
分類:字節流 輸出流 處理流
作用:把對象序列化到文件里
b、構造方法
new ObjectOutputStream(OuputStream out)
c、方法:
writeObject():把對象寫到文件里
(5)注意:
a、要序列化的對象--》類一定要實現Serializable接口
Serializable接口僅僅只是一中標識,表示這個類的對象
可以被序列化的
否則異常:java.io.NotSerializableException:
b、類里的屬性必須要全部可序列化(包含其他類)
c、對于瞬態屬性(transient)不能被序列化的
d、靜態的屬性也是不能被序列化的(內存存儲只有一份)
e、serialVersionUID 5832446596546430553
-1633153781288661891
作用:在反序列化時,檢測文件里的類的信息和現在類的信息是不是
一致;如果不一致,就異常
一般:自己生成版本號,不要讓系統自動生成
當我們存多個序列化的對象的時候 需要我們先往對象流里面存入序列化對象的總個數 ,這樣方便了我們反序列化的
時候可以正確的取出對象的個數。
(6)反序列化
a、ObjectInputStream:對象輸入流
b、分類:輸入流 字節流 處理流
c、構造方法:
new ObjectInputStream(InputStream in)
d、方法
readObject():讀取對象 (強轉)
序列化 :
當我們需要不序列話的對象屬性的是時候 可以把屬性改成靜態的。這樣在 序列化和反序列化的時候 輸出對象屬性為 null
比如在 對象屬性在 聲明的時候 把屬性 設置成 static 和
Transient
當變量是用static 修飾 并且給附初始值的時候 當我們反序列的時候可以看到 此屬性賦予了相應的值。
當屬性 使用了Transient 修飾的時候 當我們設置值 并且 序列化和反序列 并沒有同時進行的時候 就不可以觀察到反序列化的值
當反序列和序列化同時操作的時候可以在短暫的觀察到此對象的屬性值。
下面的代碼可以準確的展示出 static 修飾的變量的作用:
public static void main(String args[]) throws FileNotFoundException, IOException, ClassNotFoundException {
User user = new User();
user.setAge("22");
user.setName("小明");
user.setPassword("admin");
System.out.println(user.getAge()+"\t"+user.getName()+"\t"+user.getPassword());
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("d:/user.txt"));
oos.writeObject(user);
user.setAge("33"); //在序列化后在對static修飾的變量進行一次賦值操作
oos.flush();
oos.close();
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("d:/user.txt"));
User users = (User) ois.readObject();
System.out.println(users.getAge()+"\t"+users.getName()+"\t"+users.getPassword());
}
在讀源碼的時候看到了一個 transient 修飾的變量 ,字面意思是瞬變的。在以前的開發過程中也沒用到過這個修飾語,查了一下這個修飾語的作用為使被 transient 修飾的變量在序列化的時候不會被
保存到文件中,也就是通過序列化后再被反序列化后讀取這個變量不會有值
被static修飾的變量應該也是不會被序列化的,因為只有堆內存會被序列化.所以靜態變量會天生不會被序列化。
那這里被static修飾的變量反序列化后有值又是什么鬼 這是因為 靜態變量在方法區,本來流里面就沒有寫入靜態變量,我們打印靜態變量當然會去方法區查找,我們當前 jvm 中有所以靜態變量在序列化后任然有值。 由此可以看出 static 修飾的變量本身是不會被序列化的
我們讀取的值是當前jvm中的方法區對應此變量的值