(92)操作对象流ObjectStream、管道流PipedStream、任意流RandomStream

一、操作对象:ObjectInputStream与ObjectOutputStream
被操作的对象需要实现Serializable(标记接口)
这里写图片描述

①构造函数: ObjectOutputStream(OutputStream out) :创建写入指定OutputStream的ObjectOutputStream
②public final void writeObject(Object obj) throws IOException:写入对象
在被序列化的类要实现Serializable接口(否则会抛NotSerializableException 异常- 某个要序列化的对象不能实现 java.io.Serializable 接口。 )
但是Serializable中没有方法,简单理解就是要想序列化,必须实现Serializable,否则无法序列化。

public static void write()throws IOException {
        ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("E:\\a.txt"));
        oos.writeObject(new Person("zhangsan",10,"kr"));
        oos.close();

    }

这里写图片描述
public final Object readObject() throws IOException, ClassNotFoundException

public static void read()throws IOException{
        ObjectInputStream ois=new ObjectInputStream(new FileInputStream("e:\\a.txt"));
        try {
            Object obj=ois.readObject();
            Person p=(Person)obj;
            System.out.println(p.toString());
        } catch (ClassNotFoundException e) {

            throw new RuntimeException("序列类没有找到!");
        }
        ois.close();
    }

注意①若Person中的int age;改为private int age; 对象文件将无法读取,可在类中自定义标记ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L;
②在Person中定义 static String country=”cn”;构造方法Person(String name,int age,String country)在创建对象时,改变country,序列化也不会输出该修改值,因为静态在方法区中,而对象在堆中。
③若是非静态,但是该字段也不想被序列化,可以transient int age;这样创建对象修改age,也不会改变序列化的值0。

二、PipedInputStream和PipedOutputStream

public class Read implements Runnable {

    private PipedInputStream in;
    Read( PipedInputStream in){
        this.in=in;
    }
    public void run() {
        try {
            byte[] buf=new byte[1024];
            int len=0;
            while((len=in.read(buf))!=-1) {
                System.out.print(new String(buf,0,len));
            }
            in.close();

        }catch(IOException e) {
            throw new RuntimeException("读取失败");
        }
    }
}

public class Write implements Runnable {

    private PipedOutputStream out;
    Write(PipedOutputStream out){
        this.out=out;
    }
    public void run() {
        try {
            out.write("piped come  hahah".getBytes());
            out.close();

        }catch(IOException e) {
            throw new RuntimeException("读取失败");
        }

    }
}


public static void main(String[] args)throws IOException {
        PipedInputStream in=new PipedInputStream();
        PipedOutputStream out =new PipedOutputStream();
        in.connect(out);

        Read  r=new Read(in); 
        Write   w=new Write(out);

        new Thread(r).start();
        new Thread(w).start();
    }

三、RandomAccessFile
该类不是IO体系中的子类。而是直接继承自Object。但是他是IO包中的成员,因为它本身具备读和写的功能。内部封装了一个数组,而且通过指针对数组的元素进行操作,可以通过getFilePointer获取指针位置,通过seek改变指针的位置。
完成读写的原理:内部封装了字节输入流、字节输出流 。
通过构造函数可以看出,该类只能操作文件 ,而且操作文件还得有个模式:只读r,读写rw等
* ①写文件*
write方法当数据大于8位时,只取最低8位写入文件,所以一般用writeInt

 RandomAccessFile raf=new RandomAccessFile("E:\\ran.txt","rw");
        raf.write("李四".getBytes());
        raf.writeInt(8);//

        raf.write("王五".getBytes());
        raf.writeInt(99);

文件内容如↓所示:一个空格是一个字节,空了三个字节
这里写图片描述

②读文件
这里写图片描述
一个汉字是两个字节,一个int类型的数据是4个字节,因为内部封装了数组,所以可以通过指针来确定取哪个值

public void seek(long pos)throws IOException:确定数组指针
public int skipBytes(int n) throws IOException :跳过n个字节,它只能向后跳,不能随意跳

RandomAccessFile  raf=new RandomAccessFile("E:\\ran.txt","r");
        int count=0;//确定输出第几个人的信息,第一个人:count=0;第二个人:count=1....
        raf.seek(8*count);//通过指针确定取哪个数组元素,调整对象中指针,但是要保证数据有规律
        //raf.skipBytes(8);取第二个姓名和年龄
        //取姓名:
        byte[] buf=new byte[4];
        raf.read(buf);
        String name=new String(buf);
        //取年龄
        int age=raf.readInt();//数字是int类型输入的
        System.out.println("name="+name);
        System.out.println("age="+age);

③随意位置写,随意位置改

        //随意位置写
        RandomAccessFile  raf=new RandomAccessFile("E:\\ran.txt","rw");
        raf.seek(8*3);//在第三个位置开始写入数据(可以在随意位置写)

        raf.write("周七".getBytes());
        raf.writeInt(109);
        raf.close();

       //随意位置改
        RandomAccessFile  raf=new RandomAccessFile("E:\\ran.txt","rw");
        raf.seek(8*0);//在第三个位置开始写入数据(可以在随意位置写)

        raf.write("丽丽".getBytes());
        raf.writeInt(200);
        raf.close();

上面两个操作完成后,文件如↓↓
这里写图片描述

从③可以看出,若反对向的构造函数要操作的文件不存在,则会自动创建,如果存在,原文件的数据不会覆盖。
如果模式是只读r,不会创建文件,会去读取一个已经存在的文件,若文件不存在,则会报异常
如果模式rw,操作的文件不存在,会自动创建;如果存在,则不会覆盖

应用,比如在多线程中,每个线程写不同的段,即下载资源时多线程下载

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值