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

来源:互联网 发布:网络大数据查询 编辑:程序博客网 时间:2024/05/22 04:38

一、操作对象: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