轉換流、緩衝流
轉換流,,,,, 緩衝流,,,,,Properties類,,,,,序列化流與反序列化流
轉換流
1. OutputStreamWriter類
它的作用的就是,將字串按照指定的編碼表轉成位元組,在使用位元組流將這些位元組寫出去。
public static void writeCN() throws Exception { //建立與檔案關聯的位元組輸出流物件 FileOutputStream fos = new FileOutputStream("c:\\cn8.txt"); //建立可以把字元轉成位元組的轉換流物件,並指定編碼 OutputStreamWriter osw = new OutputStreamWriter(fos,"utf-8"); //呼叫轉換流,把文字寫出去,其實是寫到轉換流的緩衝區中 osw.write("你好");//寫入緩衝區。 osw.close(); }
2. InputStreamReader類
InputStreamReader 是位元組流通向字元流的橋樑:它使用指定的字元編碼表讀取位元組並將其解碼為字元。
它使用的字符集可以由名稱指定或顯式給定,或者可以接受平臺預設的字符集。
public class InputStreamReaderDemo { public static void main(String[] args) throws IOException { //演示位元組轉字元流的轉換流 readCN(); } public static void readCN() throws IOException{ //建立讀取檔案的位元組流物件 InputStream in = new FileInputStream("c:\\cn8.txt"); //建立轉換流物件 //InputStreamReader isr = new InputStreamReader(in);這樣建立物件,會用本地預設碼錶讀取,將會發生錯誤解碼的錯誤 InputStreamReader isr = new InputStreamReader(in,"utf-8"); //使用轉換流去讀位元組流中的位元組 int ch = 0; while((ch = isr.read())!=-1){ System.out.println((char)ch); } //關閉流 isr.close(); } }
緩衝流
1 位元組緩衝流
位元組緩衝流根據流的方向,共有2個
l 寫入資料到流中,位元組緩衝輸出流 BufferedOutputStream
l 讀取流中的資料,位元組緩衝輸入流 BufferedInputStream
1.1 位元組緩衝輸出流BufferedOutputStream
1.2 位元組緩衝輸入流 BufferedInputStream
public static void main(String[] args) throws IOException { FileInputStream shuru=new FileInputStream("D:\\表約束.wmv"); //建立位元組輸出緩衝流 BufferedInputStream bis=new BufferedInputStream(shuru); //建立位元組輸出流 FileOutputStream shuchu=new FileOutputStream("D:\\io0512\\a\\字元流.wmv"); //建立位元組輸出 BufferedOutputStream bos=new BufferedOutputStream(shuchu); //複製 int len=0; while((len=bis.read())!=-1){ bos.write(len); } bis.close(); bos.close(); }
2 字元緩衝流
l 字元緩衝輸入流 BufferedReader
l 字元緩衝輸出流 BufferedWriter
完成文字資料的高效的寫入與讀取的操作
字元緩衝輸出流 BufferedWriter
l 方法:
void newLine() 根據當前的系統,寫入一個換行符
public class BufferedWriterDemo { public static void main(String[] args) throws IOException { //建立流 //基本字元輸出流 FileWriter fileOut = new FileWriter("file.txt"); //把基本的流進行包裝 BufferedWriter out = new BufferedWriter(fileOut); //2,寫資料 for (int i=0; i<5; i++) { out.write("hello"); out.newLine(); } //3,關閉流 out.close(); } }
字元緩衝輸入流 BufferedReader
l 方法
publicStringreadLine() 讀取一個文字行,包含該行內容的字串,不包含任何行終止符,如果已到達流末尾,則返回 null
public class BufferedReaderDemo { public static void main(String[] args) throws IOException { //1,建立流 BufferedReader in = new BufferedReader(new FileReader("file.txt")); //2,讀資料 //一次一個字元 //一次一個字元陣列 //一次讀取文字中一行的字串內容 String line = null; while( (line = in.readLine()) != null ){ System.out.println(line); } //3,關閉流 in.close(); } }
文字複製,一個字元陣列一個數組讀
public class Demo04 { public static void main(String[] args) throws IOException { //建立字元輸入 FileReader shuru=new FileReader("D:\\io0512\\utf-8.txt"); BufferedReader br=new BufferedReader(shuru); FileWriter shuchu=new FileWriter("D:\\io0512\\a\\utf-8.txt"); BufferedWriter bw=new BufferedWriter(shuchu); int len=0; char[] ch=new char[2]; while((len=br.read(ch))!=-1){ bw.write(ch,0,len); bw.flush(); } br.close(); bw.close(); } }
一個位元組一個位元組複製
public static void main(String[] args) throws IOException { FileInputStream shuru=new FileInputStream("D:\\表約束.wmv"); //建立位元組輸出緩衝流 BufferedInputStream bis=new BufferedInputStream(shuru); //建立位元組輸出流 FileOutputStream shuchu=new FileOutputStream("D:\\io0512\\a\\字元流.wmv"); //建立位元組輸出 BufferedOutputStream bos=new BufferedOutputStream(shuchu); //複製 int len=0; while((len=bis.read())!=-1){ bos.write(len); } bis.close(); bos.close(); } }
一行一行的讀
public static void main(String[] args) throws IOException { //chuang減字元輸入流 FileReader shuru=new FileReader("D:\\io0512\\utf-8.txt"); BufferedReader br=new BufferedReader(shuru); FileWriter shuchu=new FileWriter("D:\\io0512\\utf-82.txt"); BufferedWriter bw=new BufferedWriter(shuchu); //複製 String len=null; while((len=br.readLine())!=null){//一行一行讀 bw.write(len); bw.newLine();//換行 bw.flush(); } br.close(); bw.close(); }
流的操作規律
IO流中物件很多,解決問題(處理裝置上的資料時)到底該用哪個物件呢?
把IO流進行了規律的總結(四個明確):
l 明確一:要操作的資料是資料來源還是資料目的。
源:InputStream Reader
目的:OutputStream Writer
先根據需求明確要讀,還是要寫。
l 明確二:要操作的資料是位元組還是文字呢?
源:
位元組:InputStream
文字:Reader
目的:
位元組:OutputStream
文字:Writer
已經明確到了具體的體系上。
l 明確三:明確資料所在的具體裝置。
源裝置:
硬碟:檔案 File開頭。
記憶體:陣列,字串。
鍵盤:System.in;
網路:Socket
目的裝置:
硬碟:檔案 File開頭。
記憶體:陣列,字串。
螢幕:System.out
網路:Socket
完全可以明確具體要使用哪個流物件。
l 明確四:是否需要額外功能呢?
額外功能:
轉換嗎?轉換流。InputStreamReader OutputStreamWriter
高效嗎?緩衝區物件。BufferedXXX
InputStream
FileInputStream
BufferedInputStream
OuputStream
FileOutputStream
BufferedOuputStream
Writer
OutputStreamWriter
FileWriter
BufferedWriter
Reader
InputStreamReader
FileReader
BufferedReader
Properties類
Properties
類表示了一個持久的屬性集。Properties
可儲存在流中或從流中載入。屬性列表中每個鍵及其對應值都是一個字串。
特點:
1、Hashtable的子類,map集合中的方法都可以用。
2、該集合沒有泛型。鍵值都是字串。
3、它是一個可以持久化的屬性集。鍵值可以儲存到集合中,也可以儲存到持久化的裝置(硬碟、U盤、光碟)上。鍵值的來源也可以是持久化的裝置。
4、有和流技術相結合的方法。
public static void main(String[] args) { //建立Pro集合 Properties pro=new Properties(); pro.put("a", "18");//存值 pro.put("b", "16"); System.out.println(pro.getProperty("a"));//輸出18,取值 System.out.println(pro.getProperty("b"));//輸出16 }
public static void main(String[] args) throws IOException { Properties pro=new Properties();//建立Propertues物件 pro.put("name","Amy"); pro.put("age", "19");
//明確properties的路徑 FileOutputStream fos=new FileOutputStream("src/com/oracle/demo02/pro.properties",true); pro.store(fos, "");//註釋,註釋不寫顯示當前時間 }
l load(InputStream) 把指定流所對應的檔案中的資料,讀取出來,儲存到Propertie集合中
l load(Reader)
l store(OutputStream,commonts)把集合中的資料,儲存到指定的流所對應的檔案中,引數commonts代表對描述資訊
l stroe(Writer,comments);
load讀取
序列化流與反序列化流
建立物件的方式:一種是new,一種是物件序列化
ObjectOutputStream 將 Java 物件的基本資料型別和圖形寫入 OutputStream。可以使用 ObjectInputStream 讀取(重構)物件。通過在流中使用檔案可以實現物件的持久儲存。
序列化:將一個物件封裝到檔案中(ObjectOutputStream)
//序列化 public class Demo01 {//將一個物件封存到檔案中 public static void main(String[] args) throws IOException { //明確目的地 FileOutputStream fos=new FileOutputStream("D:\\io0512\\person.txt"); //建立序列化流 ObjectOutputStream oos=new ObjectOutputStream(fos); oos.writeObject(new Person("張三",20)); oos.close(); } }
反序列化:將封裝好的檔案讀出來(ObjectInputStream)
用於從流中讀取物件的
//反序列化 public class Demo02 {//將封存的對向讀回來 public static void main(String[] args) throws ClassNotFoundException, IOException { //明確資料來源 FileInputStream fis=new FileInputStream("D:\\io0512\\person.txt"); //建立反序列化流物件 ObjectInputStream ois=new ObjectInputStream(fis); //讀取物件 Person p=(Person)ois.readObject(); System.out.println(p);//列印存好的資訊,Person【name=張三,age=18】 ois.close(); } }
Person類
public class Person implements Serializable{//序列化介面 public static String name;//靜態修飾不屬於物件,屬於類,不被序列化(序列化是物件) private transient int age;//不需要被序列化的屬性可以加transient,就不被序列化,寫的值就不能被讀出來 //定死uid的序列化號,保證txt和person裡的序列號一致 private static final long serialVersionUID=123L;//序列化號 public String toString() { return "Person [name=" + name + ", age=" + age + "]"; } public Person(String name, int age) { super(); this.name = name; this.age = age; } public Person() { super(); } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
序列化介面
當一個物件要能被序列化,這個物件所屬的類必須實現Serializable介面。否則會發生異常NotSerializableException異常。
同時當反序列化物件時,如果物件所屬的class檔案在序列化之後進行的修改,那麼進行反序列化也會發生異常InvalidClassException。發生這個異常的原因如下:
l 該類的序列版本號與從流中讀取的類描述符的版本號不匹配
l 該類包含未知資料型別
l 該類沒有可訪問的無引數構造方法
Serializable標記介面。該介面給需要序列化的類,提供了一個序列版本號。serialVersionUID. 該版本號的目的在於驗證序列化的物件和對應類是否版本匹配。
瞬態關鍵字transient
當一個類的物件需要被序列化時,某些屬性不需要被序列化,這時不需要序列化的屬性可以使用關鍵字transient修飾。只要被transient修飾了,序列化時這個屬性就不會序列化了。
同時靜態修飾也不會被序列化,因為序列化是把物件資料進行持久化儲存,而靜態的屬於類載入時的資料,不會被序列化。
不被序列化就無法寫入資料,讀取到的是預設值