Java IO流 四

对象流

在这里插入图片描述
在这里插入图片描述

package demo10;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;

public class ObjectStream {
    public static void main(String[] args) {
        //序列化:将内存中的java对象保存到磁盘中或者通过网络传输出去
        ObjectOutputStream oos = null;
        try {
            oos = new ObjectOutputStream(new FileOutputStream("object.txt"));
            oos.writeObject(new String("I love java"));
            oos.flush();

        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if (oos != null) {
                try {
                    oos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

在这里插入图片描述
这个文件不是用来双击打开看的,就是把序列化的对象持久的保存在磁盘上。

package demo10;

import java.io.*;

public class ObjectStream {
    public static void main(String[] args) {
        ObjectInputStream ois = null;
        try {
            ois = new ObjectInputStream(new FileInputStream("object.txt"));

            Object o = ois.readObject();

            String str = (String) o;

            System.out.println(str);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } finally {
            if(ois != null){
                try {
                    ois.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }



    }

}

在这里插入图片描述
这个操作就反序列化了,将磁盘文件中的对象还原为内存中的java对象。

自定义类实现序列化和反序列化

标识接口 Serializable

在这里插入图片描述
在这里插入图片描述

package demo10;

import java.io.Serializable;

public class Person implements Serializable {

    public static final long serialVersionUID = 475463534532L;
    
    private String name;
    private int age;

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

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

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

package demo10;

import java.io.*;

public class ObjectStream {
    public static void main(String[] args) {

        ObjectOutputStream oos = null;
        try {
            oos = new ObjectOutputStream(new FileOutputStream("object.txt"));
            oos.writeObject(new String("I love java"));
            oos.flush();

            oos.writeObject(new Person("Hawkeye",20));
            oos.flush();

        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if (oos != null) {
                try {
                    oos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        ObjectInputStream ois = null;
        try {
            ois = new ObjectInputStream(new FileInputStream("object.txt"));

            Object o = ois.readObject();

            String str = (String) o;
            Person p = (Person) ois.readObject();

            System.out.println(str);
            System.out.println(p);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } finally {
            if(ois != null){
                try {
                    ois.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }
    }
}

在这里插入图片描述

serialVersionUID的理解

在这里插入图片描述
如果我们对一个带UID的Person类序列化,那么进行一些操作比如添加一个属性id,重写toString,反序列化读回来的仍然是那个Person而且id为默认值0,如果我们对一个不带UID的Person类序列化,再执行上述操作,会报异常。
在这里插入图片描述
简而言之:一个对象,作为序列化的二进制流,如果没有UID,它的类改变了,就还原不回来了。

其他要求

在这里插入图片描述

所有属性都需要可序列化

transient关键字

我们都知道一个对象只要实现了Serilizable接口,这个对象就可以被序列化,java的这种序列化模式为开发者提供了很多便利,我们可以不必关系具体序列化的过程,只要这个类实现了Serilizable接口,这个类的所有属性和方法都会自动序列化 。然而在实际开发过程中,我们常常会遇到这样的问题,这个类的有些属性需要序列化,而其他属性不需要被序列化,打个比方,如果一个用户有一些敏感信息(如密码,银行卡号等),为了安全起见,不希望在网络操作(主要涉及到序列化操作,本地序列化缓存也适用)中被传输,这些信息对应的变量就可以加上transient关键字。换句话说,这个字段的生命周期仅存于调用者的内存中而不会写到磁盘里持久化。
总之,java 的transient关键字为我们提供了便利,你只需要实现Serilizable接口,将不需要序列化的属性前添加关键字transient,序列化对象的时候,这个属性就不会序列化到指定的目的地中。
在这里插入图片描述

static修饰的属性不能被序列化

随机存取文件流

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

package demo10;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;

public class RandomTest {
  public static void main(String[] args) {
    //
    RandomAccessFile raf = null;
    RandomAccessFile raf2 = null;
    try {
      raf = new RandomAccessFile(new File("1.png"), "r");
      raf2 = new RandomAccessFile(new File("11.png"), "rw");

      byte[] buffer = new byte[1024];
      int len;
      while ((len = raf.read(buffer)) != -1) {
        raf2.write(buffer, 0, len);
      }

    } catch (IOException e) {
      e.printStackTrace();
    } finally {
      if (raf != null && raf2 != null) {
        try {
          raf.close();
        } catch (IOException e) {
          e.printStackTrace();
        }
        try {
          raf2.close();
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
    }
  }
}

在这里插入图片描述
发现可以完成文件的复制。
下面我们新建一个1.txt
在这里插入图片描述

package demo10;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;

public class RandomTest {
  public static void main(String[] args) {

    RandomAccessFile raf = null;

    try {

      raf = new RandomAccessFile(new File("1.txt"), "rw");

      raf.write("xyz".getBytes());

    } catch (IOException e) {
      e.printStackTrace();
    } finally {
      if (raf != null) {
        try {
          raf.close();
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
    }
  }
}

在这里插入图片描述
结果如果本文件存在,则不是对文件直接覆盖,而是从源文件开头一个个覆盖,这里表现为xyz覆盖abc,按内容长度覆盖。
在这里插入图片描述

RandomAccessFile实现对数据插入

seek方法

package demo10;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;

public class RandomTest {
  public static void main(String[] args) {

    RandomAccessFile raf = null;

    try {

      raf = new RandomAccessFile(new File("1.txt"), "rw");
      //将指针调到角标为3的位置
      raf.seek(3);
      raf.write("xyz".getBytes());

    } catch (IOException e) {
      e.printStackTrace();
    } finally {
      if (raf != null) {
        try {
          raf.close();
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
    }
  }
}

在这里插入图片描述
从3开始往后覆盖。

下面实现插入
更改1.txt如下

在这里插入图片描述

package demo10;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;

public class RandomTest {
  public static void main(String[] args) {

    RandomAccessFile raf = null;

    try {

      raf = new RandomAccessFile(new File("1.txt"), "rw");
      //将指针调到角标为3的位置
      raf.seek(3);
      //减少stringbuilder底层char数组扩容
      StringBuilder sb = new StringBuilder((int) new File("1.txt").length());
      //保存指针3后面的所有数据到sb中
      byte[] buffer = new byte[20];
      int len;
      while ((len = raf.read(buffer))!=-1){
        sb.append(new String(buffer,0,len));
      }
      //此时指针在最后,需要调回来
      raf.seek(3);
      raf.write("xyz".getBytes());
      //写出去之后指针自动在z后面,再写sb中内容
      raf.write(sb.toString().getBytes());

    } catch (IOException e) {
      e.printStackTrace();
    } finally {
      if (raf != null) {
        try {
          raf.close();
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
    }
  }
}

实现了从第三个插入xyz
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值