Java IO流详解(四)

Serializable序列化

1 对象的序列化

    class Person implements Serializable {
        private String name;
        private int age;

        public Person(String name, int age) {
            this.name = name;
            this.age = age;
        }

        public String toString() {
            return "Name:" + this.name + ", Age:" + this.age;
        }
    }

    public class serialTest {
        public static void main(String[] args) {
            String path = "D:\\Program Files (x86)\\ADT\\workspace\\JavaIO\\demoTest.txt";

            Person p1 = new Person("zhangsan",12);
            Person p2 = new Person("lisi",14);

            //此处创建文件写入流的引用是要给ObjectOutputStream的构造函数玩儿
            FileOutputStream fos = null;
            ObjectOutputStream oos = null;
            try {
                fos = new FileOutputStream(path);
                oos = new ObjectOutputStream(fos);

                //这里可以写入对象,也可以写入其他类型数据
                oos.writeObject(p1);
                oos.writeObject(p2);
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    oos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

结果:

2 反序列化

package com.yin.serialize;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
public class serialTestFan {
    public static void main(String[] args) {
        String path = "D:\\Program Files (x86)\\ADT\\workspace\\JavaIO\\demoTest.txt";

        //好吧,这里代码写得着实有点长了,还要抛异常什么的
        //如果你也看的烦,那就在主方法上抛吧,构造方法里用匿名对象就好了
        //什么?别告诉我你不知道匿名对象
        FileInputStream fis = null;
        ObjectInputStream ois = null;
        try {
            fis = new FileInputStream(path);
            ois = new ObjectInputStream(fis);

            //这里返回的其实是一个Object类对象
            //因为我们已知它是个Person类对象
            //所以,就地把它给向下转型了
            Person p = (Person)ois.readObject();
            System.out.println(p);
            Person p2 = (Person)ois.readObject();
            System.out.println(p2);
//            Person p3 = (Person)ois.readObject();
//            if (p3 == null) {
//              System.out.print("p3==null");
//          }else {
//              System.out.println(p3);
//          }

            //抛死你,烦烦烦~!!!
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } finally {
            try {
                //还是要记得关闭下流
                ois.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

结果:

对应于上面序列化时写入的对象。

值得注意的是,如果把注释的代码去掉注释,则出现EOFException异常,也就是说读取完数据对象之后,不允许往下读取了。只能有多少对象数据读取多少对象。

3 管道流

线程的通信

package com.yin.serialize;
import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;

//实现Runnable接口,实现一个读的线程
class Read implements Runnable {
    private PipedInputStream in;
    //将需要读的管道流传入到构造函数中
    public Read(PipedInputStream in) {
        this.in = in;
    }

    //实现读这一线程
    public void run() {
        try {
            byte[] buf = new byte[1024];
            int temp = 0;
            //循环读取
            //read是一个阻塞方法,需要抛异常
            //此处把打印流的代码也加入进来
            //是因为如果没有读取到数据,那么打印的代码也无效
            while((temp = in.read(buf)) != -1) {
                String str = new String(buf,0,temp);
                System.out.println(str);
            }
        } catch (IOException e) {
            //其实这里应抛出一个自定义异常的
            //暂时我还没弄清楚
            e.printStackTrace();
        } finally {
            try {
                //我已经抛火了,这只是为了提醒自己异常很重要
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

//这里实现一个写的类
class Write implements Runnable {
    private PipedOutputStream out;
    //将管道输入流传进来
    public Write(PipedOutputStream out) {
        this.out = out;
    }

    public void run() {
        try {
            //这里开始写出数据
            out.write("管道操作=========看到没,就是这句!!".getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                //其实应该可以把这个关闭方法写到上面那个try里边
                //但是这样感觉怪怪的,逻辑不大对
                out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

public class Demo {
    public static void main(String[] args) {
        PipedInputStream in = new PipedInputStream();
        PipedOutputStream out = new PipedOutputStream();
        try {
            //连接管道
            in.connect(out);

            //创建对象,开启线程
            //此处同样放进try...catch里面
            //因为如果没有链接管道,下面操作无意义
            Read r = new Read(in);
            Write w = new Write(out);
            //把已经实现好run方法的对象放入线程中执行
            new Thread(r).start();
            new Thread(w).start();

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

结果:

我们知道,字节流和字符流都需要数组来进行流的中转

而管道流则直接串联两条流,一边发送数据,一边接收

然而,同时通信的的两种状态,如何才能确定发送和接收的一致性呢

那么,就需要用到线程,无论是接收方还是发送方先执行

总会造成一个线程的阻塞状态,从而等待另一方的数据传过来

总体而言,管道流的目的,也就是为了线程通信

此外,还有PipedReader和PipedWriter类,操作原理都一样

4 DataOutputStream和DataInputStream类

基本数据类型的写入

package com.yin.serialize;

import java.io.DataOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class DataStreamTest {
    public static void main(String[] args) {
        String path = "D:\\Program Files (x86)\\ADT\\workspace\\JavaIO\\demoTest.txt";

        DataOutputStream d = null;
            try {
                //此处需要传入一个OutputStream类的对象
                d = new DataOutputStream(new FileOutputStream(path));
                //开始写入基本数据类型
                d.writeInt(12);
                d.writeBoolean(true);
                d.writeDouble(12.2223);
                d.writeChar(97);
                //刷新流
                d.flush();

            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    d.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
    }
}

结果:

5 基本数据类型的读取

import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.IOException;

public class DataReadTest {
    public static void main(String[] args) {
        String path = "D:\\Program Files (x86)\\ADT\\workspace\\JavaIO\\demoTest.txt";

        DataInputStream d = null;
            try {
                d = new DataInputStream(new FileInputStream(path));
                //按存储顺序读取基本数据类型
                System.out.println(d.readInt());
                System.out.println(d.readBoolean());
                System.out.println(d.readDouble());
                System.out.println(d.readChar());

            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    d.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
    }
}

结果:

这个结果与上面的数据写入顺序一致。也就是说读取数据和写入数据一致!!注意!否则会发生数据的打印错误!

参考 :http://www.cnblogs.com/nerxious/archive/2012/12/17/2822365.html

源码下载

时间: 2024-10-12 10:28:24

Java IO流详解(四)的相关文章

Java IO流详解(五)——缓冲流

缓冲流也叫高效流,是处理流的一种,即是作用在流上的流.其目的就是加快读取和写入数据的速度. 缓冲流本身并没有IO功能,只是在别的流上加上缓冲效果从而提高了效率.当对文件或其他目标频繁读写或操作效率低,效能差时.这时使用缓冲流能够更高效的读写信息.因为缓冲流先将数据缓存起来,然后一起写入或读取出来.所以说,缓冲流还是很重要的,在IO操作时加上缓冲流提升性能. Java IO流中对应的缓冲流有以下四个: 字节缓冲流:BufferedInputStream.BufferedOutputStream 字

java IO流详解(一)

从本篇博文开始,详细讲解JAVA IO流的基本操作,力求每一个例子都给大家一个DEMO,在最终完成的时候,我会贴出最终的源码,方便大家交流学习. 上一篇博文中转载了大神的博文和图片,非常好! 文章链接如下:Java IO流 下面一个个的用实例进行讲解每个IO流的基本用法. 1 File文件 public static void main(String[] args) throws IOException { File file = new File("."); myPrint(file

《java基础知识》Java IO流详解

Java IO概念 1. 用于设备之间的数据传输. 2. Java 将操作数据流的功能封装到了IO包中. 3. 数据流流向分:输入流和输出流,操作对象为文件. 4. 流按照操作数据分:字节流(通用)和字符流. 5. 将计算机语言:二进制数据转换成文件显示到电脑上. IO包:继承关系图: 字符流: Reader :读取字符流,方法见API. Writer :写入字符流,方法见API. 案例(Writer ): import java.io.*; public class var { public

Java IO流详解(二)——File类

在上一章博客中简单的介绍了Java IO流的一些特征.也就是对文件的输入输出,既然至始至终都离不开文件,所以Java IO流的使用得从File这个类讲起. File类的描述:File类是文件和目录路径名的抽象表示形式,主要用于文件和目录的创建.查找和删除等操作.即Java中把文件或者目录(文件夹)都封装成File对象.也就是说如果我们要去操作硬盘上的文件或者目录只要创建File这个类即可. 不过要注意的是File类只是对文件的操作类,只能对文件本身进行操作,不能对文件内容进行操作. 1.File

Java IO流详解

初学java,一直搞不懂java里面的io关系,在网上找了很多大多都是给个结构图草草描述也看的不是很懂.而且没有结合到java7 的最新技术,所以自己来整理一下,有错的话请指正,也希望大家提出宝贵意见. 首先看个图:(如果你也是初学者,我相信你看了真个人都不好了,想想java设计者真是煞费苦心啊!) 这是java io 比较基本的一些处理流,除此之外我们还会提到一些比较深入的基于io的处理类,比如console类,SteamTokenzier,Externalizable接口,Serializa

Java IO流详解(五)

使用的是InputStreamReader和OutputStreamWriter,它们本身属于的是reader和writer字符流,我们之所以会用到这些转化流是因为系统有时候只给我们提供了字节流,为了方便操作,要用到字符流.比如说System.in标准输入流就是字节流.你想从那里得到用户在键盘上的输入,只能是以转换流将它转换为Reader以方便自己的程序读取输入.再比如说Socket里的getInputStream()很明显只给你提供字节流,你要想读取字符,就得给他套个InputStreamRe

Java IO流详解(三)

Scanner类 1 从键盘读取 public class ScannerTest { public static void main(String[] args ) { Scanner input = new Scanner(System.in); System.out.println("请输出一个整数:"); int i = input.nextInt(); System.out.println("你输入的整数是:" + i); } } 结果: 2 从字符串读取

Java IO流详解(二)

1 文件对象 public class CreateFile { public static void main(String[] args) { //创建要操作的文件路径和名称 //其中,File.separator表示系统相关的分隔符,Linux下为:/ Windows下为:\\ //path在此程序里面代表父目录,不包含子文件 String path = "D:\\Program Files (x86)\\ADT\\workspace\\JavaIO\\parent"; //ch

java知识点分享,IO流详解!

Java知识IO流详解有人觉得IO知识不太重要,其实不然,IO的使用范围很广,最能体现IO价值的就是网络上的数据传递,尤其是进入互联网时代后,各种常见的分布式架构,都少不了IO的体现.并且很多大厂的面试题中都会体现出对IO的重视,包括衍生出来的NIO.序列化等等.因此学好IO,变成了一件很重要的事情.IO基本概念IO可以简单的理解成INPUT和OUT,代表输入输出的意思.输入就是读,输出就是写.IO可以读写硬盘.光盘.内存.键盘.网络等资源上的数据.流IO中的流就相当于现实生活中的水流一样,一打