Java学习day40-处理流之六:对象流和随机存取流

一、对象流

1.因为需要保存对象到硬盘(对象的持久化)和进行对象的网络传输,产生了对象的输入与输出流。(ObjectInputStream和ObjectOutputStream)

2.用于存储和读取对象的处理流。它强大之处就是可以把Java中的对象写入到数据源中,也能把对象从数据源中还原回来。

3.序列化(Serialize):用ObjectOutputStream类将一个Java对象写入IO流中。

   反序列化(Deserialize):用ObjectInputStream类从IO流中恢复该Java对象。

4.ObjectInputStream和ObjectOutputStream不能序列化static和transient修饰的成员变量。(序列化和反序列化针对的是对象的各种属性,不包括类的属性)

二、对象的序列化

1.如果需要让某个对象支持序列化机制,则必须让其类是可序列化的,因此该类必须实现如下两个接口之一:①Serializable ②Extrenalizable

2.凡是实现Serializable接口的类都有一个表示序列化版本标识符的静态变量:private static final long serialVersionUID;

  ①serialVersionUID用来表示类的不同版本间的兼容性

  ②如果类没有显示定义这个静态变量,它的值是Java运行时环境根据类的内部细节自动生成。若类的源代码做了修改,serialVersionUID也可能发生变化,故建议,显示声明。

3.显示定义serialVersionUID的用途

  ①希望类的不同版本对序列化兼容,因此需要确保类的不同版本具有相同的serialVersionUID。

  ②不希望类的不同版本对序列化兼容,因此需要确保类的不同版本具有不同的serialVersionUID。

三、使用对象流序列化对象

1.若某个类实现了Serializable接口,该类的对象就是可序列化的:

  ①创建一个ObjectOutputStream

  ②调用ObjectOutputStream对象的writerObject(对象)方法输出可序列化对象,注意:写出一次,操作flush().

2.反序列化:

  ①创建一个ObjectInputStream

  ②调用readObject()方法读取流中的对象

强调:如果某个类的字段不是基本数据类型或String类型,而是领一个引用类型,那么这个引用类型必须是可序列化的,否则拥有该类型的Field的类也不能序列化。

package day18;

import java.io.Serializable;

/**
 * 可以序列化和反序列化的对象
 * */
public class Person implements Serializable{

    /**
     *一个表示序列化版本标识符的静态变量
     *用来表明类的不同版本间的兼容性
     */
    private static final long serialVersionUID = 1L;
    
    String name;
    int age;
    
}
package day18;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

/**
 * 序列化和反序列化
 * 注意:对象的序列化和反序列化使用的类严格一致(包名、类名、结构等等所有都要一致)
 * 
 * */
public class Test5 {
    public static void main(String[] args){
        try {
//            Test5.testSerialize();
            Test5.testDeserialize();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    
    /**
     * 对象的序列化
     * */
    public static void testSerialize() throws Exception{
        //定义对象的输出流,把对象的序列化之后的流放到指定的文件中
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("F:\\testdemo\\demo\\src\\day18\\tt9.txt"));
        
        Person p = new Person();
        p.name = "zhangsan";
        p.age = 13;
        
        out.writeObject(p);
        out.flush();//刷写数据到硬盘
        
        out.close();
    }
    
    
    /**
     * 对象的反序列化
     * */
    public static void testDeserialize() throws Exception{
        //创建对象输入流对象,从指定的文件中把对象序列化后的流读取出来
        ObjectInputStream in = new ObjectInputStream(new FileInputStream("F:\\testdemo\\demo\\src\\day18\\tt9.txt"));
        
        Object obj = in.readObject();
        
        Person p = (Person)obj;
        
        System.out.println(p.name);
        System.out.println(p.age);
        
        in.close();
    }
}

打印结果:

zhangsan
13

 

四、随机存取流(RandomAccessFile类)

1.RandomAccessFile类支持“随机访问”的方式,程序可以跳到文件的任何地方来读、写文件。

  ①支持只访问文件的部分内容。

  ②可以向已存在的文件后追加内容。

2.RandomAccessFile对象包含一个记录指针,用以标示当前读写处的位置。

3.RandomAccessFile类对象可以自由移动记录指针:

  ①long getFilePointer():获取文件记录指针的当前位置。

  ②void seek(long pos):将文件记录指针定位到pos位置。

3.构造器:

  ①public RandomAccessFile(File file,String mode)

  ②public RandomAccessFile(String name, string mode)

4.创建RandomAccessFile类实例需要指定一个mode参数,该参数指定RandomAccessFile的访问模式:

  ①r:以只读方式打开

  ②rw:打开以方便读取和写入

  ③rwd:打开以便读取和写入;同步文件内容的更新

  ④rws:打开以便读取和写入;同步文件内容和元数据的更新

package day18;

import java.io.RandomAccessFile;

/**
 * 程序的随机读写
 * 程序可以跳到文件的任何地方来读、写文件
 * */
public class Test6 {
    public static void main(String[] args){
        try {
//            Test6.testRandomAccessFileRead();
            Test6.testRandomAccessFileWriter();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    
    /**
     * 随机读文件
     * */
    public static void testRandomAccessFileRead() throws Exception{
        //RandomAccessFile的构造有两个参数,参数一是读写文件的路径,参数二是指定RandomAccessFile的访问模式
        //最常用的是r和rw
        RandomAccessFile ra = new RandomAccessFile("F:\\testdemo\\demo\\src\\day18\\tt10.txt","r");
        
        //通过设置读取文件内容的起始点,来达到从文件的任意位置读取
        ra.seek(0);//设置读取文件内容的起始点
        
        byte[] b = new byte[1024];
        
        int len = 0;
        
        while((len = ra.read(b)) != -1){
            System.out.println(new String(b,0,len));
        }
        
        ra.close();
    }
    
    
    /**
     * 随机写入文件内容
     * */
    public static void testRandomAccessFileWriter() throws Exception{
        RandomAccessFile ra = new RandomAccessFile("F:\\testdemo\\demo\\src\\day18\\tt10.txt","rw");
        
        //注意:如果是在文件的开头或者中间的某个位置开始写的话,就会用写的内容覆盖掉等长度的原内容
        ra.seek(0);//设置写的起始点,0代表从开头写
//        ra.seek(ra.length());//ra.length()代表从文件的最后结尾写,也就是文件内容的追加
        
        ra.write("你好".getBytes());
        
        ra.close();
    }
}

 

五、流的基本应用小结

1.流是用来处理数据的。

2.处理数据时,一定要先声明数据源,与数据目的地。

  ①数据源可以是文件,可以是键盘。

  ②数据目的地可以是文件。显示器或者其他设备。

3.流只是在帮助数据进行传输,并对传输的数据进行处理,比如过滤处理、转换处理等。

 

posted @ 2020-03-31 22:25  苏胖胖  阅读(252)  评论(0)    收藏  举报