Java之I/O流(二)

一:字节流:
1.输入字节流:InputStream(子类为FileInputStream);
输出字节流:OutputStream(子类为FileOutputStream);
但是由于这些字节流每一次读取或写入都需要与磁盘进行接触,效率太低,因此我们出现了一个BufferedInputStream和BufferedOutputStream来缓冲,每次缓冲满了就与磁盘进行接触,减少了接触次数来提高效率。
举例:比较不加缓冲的功能的读取与加缓冲的功能的读取的效率。
未优化的代码:

public class Demo1 {
    public static void main(String[] args)throws IOException {
        long start = System.currentTimeMillis();
        FileInputStream stream = new FileInputStream("F:\\java知识\\day09\\avi\\02_String练习_字符串反转.exe");
       while (true){
           int i = stream.read();
           if(i==-1){
            break;
           }
       }
       stream.close();
        long end = System.currentTimeMillis();
        long   time=end-start;
        System.out.println("共耗时"+time);
    }
}

这里写图片描述
优化后代码:

public class Demo2  {
    public static void main(String[] args) throws IOException {
        long start = System.currentTimeMillis();
        BufferedInputStream reader = new BufferedInputStream(new FileInputStream("F:\\java知识\\day09\\avi\\02_String练习_字符串反转.exe"));
        while(true){
            int read = reader.read();
            if(read==-1){
                break;
            }

        }
        long end = System.currentTimeMillis();
        long time =end-start;
        System.out.println("优化后的时间为:"+time);
    }
}

结果:这里写图片描述
2:ByteInputStream和ByteOutputStream的介绍:
它们是将一个数组转化为输入流或者是将字节写入一个数组当中去
举例:

public class Demo3 {
    public static void main(String[] args) {
        //读取
        ByteArrayInputStream bytes = new ByteArrayInputStream(new byte[]{1, 2, 3});
        while(true){
            int i = bytes.read();
          if(i==-1){
              break;
          }
            System.out.println(i);
        }
        System.out.println("-------------------");
        //写入
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        stream.write(3);
        stream.write(4);
        stream.write(98);
        byte[] bytes1 = stream.toByteArray();
        System.out.println(Arrays.toString(bytes1));


    }
}

结果:这里写图片描述
二:字符流
1:概述:分为Reader和Writer两个类
2:Reader的介绍
Reader:InputStreamReader:可以将一个字节流转换为字符流
BufferedReader:增强功能可以将按行来读取(装饰者模式);
FileReader:(在读取的时候字符的编码格式为系统默认的格式不可以随意更改)
3:Writer的介绍:
Writer:InputStreamWriter:可以将字节流转化为字符流
BufferedWriter :可以按行来写入
PrintWriter:也是可以按行来写入
Writer:将字符来写入;
print:将字符转换为字符串来写入
FileWriter也是固定了格式
三:序列化
1:序列化的概述:将一个文件转换为一个字节序列并且存储起来的过程(可实现永久保存);
2:如何实现序列化:
(1)首先要让类实现一个Serializable的接口;(注意:如果没有实现Serializable的接口的话就会报出NotSerializableException的异常)
(2)然后利用ObjectOutputStream来写入需要序列化的对象,要求对象的属性都是可以序列化的,如果某个属性不想被实例化的话就要加一个关键字transient
举例:

public class Demo4 {
    public static void main(String[] args) throws IOException {
        //一个对象的序列化
        Person p=new Person();
        p.setName("张三");
        p.setAge(10);
        ObjectOutputStream os=new ObjectOutputStream(new FileOutputS![这里写图片描述](https://img-blog.csdn.net/20180811232808235?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MDg0MzYyNA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)tream("D:\\p.txt"));
        os.writeObject(p);
        os.writeObject("3");
        os.close();
    }
}

结果:
这里写图片描述
四:反序列化
1:反序列化的概述:将字节内容转换为一个对象ObjectInputStream读取字节的内容,将其转换为java对象,不仅可以读取一个对象还可以读取或写入基本类型,但是注意写入与读取的顺序要保持一致,否则就会出现EOFException
建议在文件的最后一个对象中加入null值,这样就可以判断是否被读取完毕
举例:

public class Demo5 {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream("D:\\p.txt"));
       Person o = (Person) inputStream.readObject();
        System.out.println(o.toString());
        System.out.println(o.getName());
    }
}

结果:
这里写图片描述

五:创建对象的几种方式
(1):经常使用的new来创建一个对象
(2):反序列化来创建一个新的对象
(3):克隆
下面先对克隆来进行一个介绍
首先克隆一个对象就要对这个对象实现一个Cloneable的接口,再去调用clone方法。
为什么要克隆?
克隆的对象可能包含一些已经修改过的属性,而new出来的对象的属性都还是初始化时候的值,所以当需要一个新的对象来保存当前对象的“状态”就靠clone方法了。
注意:使用Cloneable接口和clone克隆的对象,仅仅是浅拷贝,如果属性为引用类型,复制的仅是地址。没有为这个属性创建新的对象
举例:

public class Demo {
    public static void main(String[] args) throws CloneNotSupportedException {
        Person p=new Person();
        p.setName("张三");
        p.setAge(20);
        Person o =(Person) p.clone();
        o.setAge(29);
        o.setName("张思");
        System.out.println(p.getName());
        System.out.println(p.getAge());
        System.out.println(o==p);

    }
}

结果:这里写图片描述
深拷贝 利用序列化和反序列化生成新的对象,也会为属性创建新的对象
举例:

public class Teacher2 implements Serializable {

    private int id;
    private String name;
    private Date birthday;

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Teacher2 clone() {
        try {
            // 序列化
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectOutputStream os = new ObjectOutputStream(bos);
            os.writeObject(this); // 写入当前对象
            byte[] bytes = bos.toByteArray(); // 字节结果

            // 反序列化
            ObjectInputStream is = new ObjectInputStream(new ByteArrayInputStream(bytes));
            Teacher2 t = (Teacher2)is.readObject();
            return t;
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    public static void main(String[] args) {
        Teacher2 t = new Teacher2();
        t.setId(1);
        t.setName("张三");
        t.setBirthday(new Date());

        Teacher2 t2 = t.clone();

        System.out.println(t == t2);
        System.out.println(t2.getBirthday());
        System.out.println(t.getBirthday());
        System.out.println(t.getBirthday() == t2.getBirthday());
    }
}

结果:
这里写图片描述

猜你喜欢

转载自blog.csdn.net/weixin_40843624/article/details/81626473