zoukankan      html  css  js  c++  java
  • I/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窗口上输入要获取的位置即可,超出位置会抛异常。

  • 相关阅读:
    git fetch pull checkout区别
    git config配置文件
    php错误以及常用笔记
    Linux chmod命令修改文件与文件夹权限的命令附实例
    学习笔记 2016-04-12
    MYSQL 【汇总数据】 【分组数据】 学习记录
    Mysql常用函数
    学习笔记
    a++ ++a 文件上传函数错误 smarty模板特点
    算法稳定性相关
  • 原文地址:https://www.cnblogs.com/wzy330782/p/5475789.html
Copyright © 2011-2022 走看看