程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA綜合教程 >> I/O流——其他流,o流

I/O流——其他流,o流

編輯:JAVA綜合教程

I/O流——其他流,o流


其他流

一、ObjectInputStream/ObjectOutputStream

① ObjectInputStream和ObjectOutputStream分別與FileInputStream和FileOutputStream一起使用時,可以對應用程序提供對對象的持久存儲。我們把對象以某種特定的編碼格式寫入稱之為“序列化”。把寫入的編碼格式內容還原成對象稱之為“反序列化”。

② 被序列化的對象必須實現Serializable接口。

 

序列化示例:

 1 //必須實現Serializable接口
 2 class Student implements Serializable{
 3     private String name;
 4     private int age;
 5     public Student(String name, int age) {
 6         super();
 7         this.name = name;
 8         this.age = age;
 9     }
10     public String getName() {
11         return name;
12     }
13     public void setName(String name) {
14         this.name = name;
15     }
16     public int getAge() {
17         return age;
18     }
19     public void setAge(int age) {
20         this.age = age;
21     }
22     @Override
23     public String toString() {
24         return "Student [name=" + name + ", age=" + age + "]";
25     }
26     
27 }

主方法:

1         Student stu=new Student("zhangsan", 30);
2         FileOutputStream fos=new FileOutputStream("d:/test.txt");
3         ObjectOutputStream oos=new ObjectOutputStream(fos);
4         oos.writeObject(stu);//把對象序列化到指定的文件輸出流中
5         oos.close();//釋放資源

 

反序列化:

主方法:

1         ObjectInputStream ois=new ObjectInputStream(new FileInputStream("d:/test.txt"));
2         try {
3             Student stu2= (Student)ois.readObject();
4             System.out.println(stu2);
5         } catch (ClassNotFoundException e) {
6             e.printStackTrace();
7         }
8         ois.close();

 

反序列化成功之後,再在Student中添加一個地址屬性。

private String address;

發現不能反序列化了,因為序列化的對象與反序列化的對象不一致。

解決辦法:Eclipse的Student類行號左邊有一個小燈,

添加一個版本號。再次進行序列化操作,新增屬性後反序列化也能成功,它會自動取出序列化中不存在的屬性。

 

二、InputStreamReader/OutputStreamWriter

①轉換流是指將字節流與字符流之間的轉換。

②轉換流的出現方便了對文本的讀寫,她在字符流與字節流之間架起了一座橋梁,使原本毫無關聯的兩種流操作能進行轉化,提高了程序的靈活性。

③ 節流中的數據都是字符時,轉成字符流操作更高效。

④ 如果使用非默認編碼保存文件或讀取文件時,需要用到轉換流。因為字節流的重載構造方法中有指定編碼格式的參數,而FileReader與FileWriter是默認編碼的文本文件。

⑤ 常見的編碼表

a)     ASCII:美國標准信息交換碼。用一個字節的7位可以表示。

b)     ISO8859-1:拉丁碼表。歐洲碼。表用一個字節的8位表示。

c)     GB2312:中國的中文編碼表。

d)     GBK:中國的中文編碼表升級,融合了更多的中文文字符號。

e)     Unicode:國際標准碼,融合了多種文字。所有文字都用兩個字節來表示,Java語言使用的就是Unicode。

f)      UTF-8:最多用三個字節來表示一個字符。

g)     ……

 

將內容以指定編碼的格式存入文件:

1         OutputStreamWriter osw=new OutputStreamWriter(new FileOutputStream("d:/code.txt"), "utf-8");
2         BufferedWriter bw=new BufferedWriter(osw);
3         bw.write("你好");
4         bw.close();

讀取文件:

1         BufferedReader br=new BufferedReader(new InputStreamReader(new FileInputStream("d:/code.txt"), "utf-8"));
2         String line=null;
3         while((line=br.readLine())!=null){
4             System.out.println(line);
5         }
6         br.close();

 

三、RandomAccessFile 隨機訪問文件

①支持對隨機訪問文件的讀取和寫入。

②隨機訪問文件的行為類似存儲在文件系統中的一個大型byte數組。存在指向該隱含數組的光標或索引,稱為文件指針。

③ 入操作從文件指針開始讀取字節,隨著對字節的讀取而前移此文件指針。

④ 如果隨機訪問文件以讀取/寫入模式創建,則輸出操作也可用;輸出操作從文件指針開始寫入字節,隨著對字節的寫入而前移此文件指針。

⑤ 寫入隱含數組末尾之後的輸入操作導致該數組擴展。

⑥ 該文件指針可用通過getFilePointer方法讀取,通過seek方法設置。

 

案例說明:創建一個Person類,內有name屬性占15個字符,即30個字節,age屬性4個字節,共34個字節。將多個Person對象放入RandomAccessFile中。然後在指定的位置上取出Person對象(名字,年齡)。

 

創建一個Person類

 1 class Person {
 2     private String name;
 3     private int age;
 4 
 5     public Person() {
 6 
 7     }
 8 
 9     public Person(String name, int age) {
10         StringBuilder builder = null;
11         if (name != null) {
12             builder = new StringBuilder(name);
13         } else {
14             builder = new StringBuilder(15);
15         }
16         builder.setLength(15);// 固定長度為15個字符,不滿15時,'\u0000'
17         this.name = builder.toString();
18         this.age = age;
19     }
20 
21     public String getName() {
22         return name;
23     }
24 
25     public void setName(String name) {
26         StringBuilder builder = null;
27         if (name != null) {
28             builder = new StringBuilder(name);
29         } else {
30             builder = new StringBuilder(15);
31         }
32         builder.setLength(15);// 固定長度為15個字符,不滿15時,'\u0000'
33         this.name = builder.toString();
34     }
35 
36     public int getAge() {
37         return age;
38     }
39 
40     public void setAge(int age) {
41         this.age = age;
42     }
43 
44     // 每個對象所占的字節數
45     public static int size() {
46         return 34;
47     }
48 
49 }

讀取名字時不用將全部字節都讀取出來,所以應該替換空字節。方法如下,將其寫在與主方法同一個類下即可

1     private static String readName(RandomAccessFile randomaccessFile)
2             throws IOException {
3         char[] name = new char[15];
4         for (int i = 0; i < name.length; i++) {
5             name[i] = randomaccessFile.readChar();
6         }
7         return new String(name).replace('\u0000', ' ');
8     }

主方法:

 1         Person[] persons = { new Person("zhangsan", 10),
 2                 new Person("lisi", 24), new Person("wangwu", 36),
 3                 new Person("zhaoliu", 66) };
 4         RandomAccessFile randomaccessFile = new RandomAccessFile(
 5                 "d:/test2.txt", "rw");
 6         // 寫入數據到RandomAccessFile這個對象中、
 7         for (int i = 0; i < persons.length; i++) {
 8             randomaccessFile.writeChars(persons[i].getName());
 9             randomaccessFile.writeInt(persons[i].getAge());
10         }
11         // 讀取指定位置上的Person對象
12         Scanner scanner = new Scanner(System.in);
13         System.out.println("讀取第幾個Person對象數據");
14         int num = scanner.nextInt();
15         // 使用seek方法來操作存取位置
16         randomaccessFile.seek((num - 1) * Person.size());
17         Person person = new Person();
18         person.setName(readName(randomaccessFile));
19         person.setAge(randomaccessFile.readInt());
20         System.out.println("姓名:" + person.getName());
21         System.out.println("年齡:" + person.getAge());
22         randomaccessFile.close();

運行後在Console窗口上輸入要獲取的位置即可,超出位置會拋異常。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved