Java基础知识点(IO流)

序列化和反序列化

  1. 序列化:Serialize ,将内存中的Java对象存储到文件中的过程

Java实现序列化有两种方式:

  • 实现serializable接口:直接实现Serializable接口的类是JDK自动把这个类的对象序列化
  • 实现externaliazble接口:如果实现public interface Externalizable extends Serializable的类则可以自己控制对象的序列化,建议能让JDK自己控制序列化的就不要让自己去控制

transient关键字修饰的属性是透明的,序列化时候就不需要考虑这个属性了

  1. 反序列化:DeSerialize,将文件中的数据重新读取到内存中,恢复成Java对象的过程

  2. Java是通过什么机制来确定是否是一个类的?
    第一,首先通过类名来确定,类名不一样,肯定不是一个类。
    第二,类名一样,通过序列化版本号进行区分。

IO流

IO流的简介和分类

通过IO可以完成硬盘文件的读和写,IO流又称输入输出流,输入和输出均是以内存作为参照。IO流按照流的方向可以分为:输入(读),输出(写)。按照读取数据方式不同进行分类:

  1. 字节流: 按照字节的方式读取数据,一次读写一个字节(Byte),等同于一次读取8个二进制位,这种流是万能的,什么文件都可以读取,包括:文本文件,图片,声音文件,视频文件等。
    例如: a中国bo账单fe
    第一次读取,一个字节,刚好读取‘a’,
    第二次读取,一个字节,读取”中“字符的一半,
    第三次读取,一个字节,读取”中“字符的另一半

  2. 字符流: 按照字符的方式读取数据,一次读取一个字符,这种流是为了方便普通文本文件而存在的,字符流不能读取图片、声音、视频文件。只能读取存文本文件。
    例如:a中国bo账单fe
    第一次读取,‘a’字符,
    第二次读取,‘中’字符

  3. 节点流、包装流(处理流):
    节点流:当一个流的构造方法需要一个流的时候,这个被传入的流就叫做节点流。
    包装流(处理流):外部负责包装的流就叫做包装流,也称为处理流。
    包装流关闭资源时候,只需要关闭外部包装流即可,内部节点流会自动关闭。

Java IO流四大家族

Java IO有四大家族,均是抽象类,分别是:
java.io.InputStream :字节输入流
java.io.OutputStream: 字节输出流
java.io.Reader:字符输入流
java.io.Writer:字符输出流

所有流均实现了java.io.Closeable接口,都是可关闭的,都有close()方法。
所有输出流也实现了java.io.Flushable接口,都是可刷新的, 都有flush()方法,输入流输出之后,一定要进行flush()操作,保证将管道、通道中剩余未输出的数据输出完成,清空管道。

Java中类名以”Stream“结尾的都是字节流,以”Reader、Weiter“结尾的都是字符流。

要掌握的16个流

文件专属

java.io.FileInputStream,字节输入流

任何形式文件都能读取,但是一个字节一个字节的读取,内存和硬盘的交互太频繁了,所以一般采取一次读取一个字节数组(byte[])的方式进行读取。

int read():一次读取一个字节,读取长度为-1时候,就是最后一次读取
int read(byte[] b): 一次读取b.length个字节,当读取长度小于b.length时候,就是最后一次读取
int available(): 返回六种剩余没有读取的字节数量
long skip(long n):跳过几个字节不读

 	FileInputStream fileInputStream = null;
   try{
        fileInputStream = new FileInputStream("C:\\Users\\Administrator\\Desktop\\temp.txt");
       // 准备读取byte数组,一次读取1024个字节
       byte[] bytes = new byte[1024];
       // 定义读取长度
       int readCount;
       while((readCount = fileInputStream.read(bytes))!=-1) {
           System.out.println(new String(bytes,0,readCount));
       }
   }catch (Exception e) {
       e.printStackTrace();
   }finally {
       // 关闭流
       if(fileInputStream != null) {
           try {
               fileInputStream.close();
           } catch (IOException e) {
               e.printStackTrace();
           }
       }
   }
java.io.FileOutputStream,字节输出流,

负责写,从内存到硬盘,为了减少内存和硬盘的交互,一般也是采用一次写入一个字节数据(byte[])方式进行写入。以不清空源文件的方式写入,要选择追加的方式写入们需要在创建对象时候设置参数true,用来表示追加写入。

FileOutputStream fileOutputStream = null;
 try{
      // 设置true 表示追加
      fileOutputStream = new FileOutputStream("C:\\Users\\Administrator\\Desktop\\temp.txt",true);
      // 定义写入数组
      //byte[] bytes = new byte[1024];
      String s = "FileOutputStreamDemo" + Calendar.getInstance();
      fileOutputStream.write(s.getBytes());
  }catch (Exception e) {
      e.printStackTrace();
  }finally {
      try {
          fileOutputStream.flush();
          fileOutputStream.close();
      } catch (IOException e) {
          e.printStackTrace();
      }
  }
java.io.FileReader(文件字符输入流)
FileReader reader = null;
try{
     // 创建文件字符输入流
     reader = new FileReader("C:\\Users\\Administrator\\Desktop\\temp.txt");
     // 开始读
     char[] chars = new char[10];
     int readCounts = 0;
     while((readCounts = reader.read(chars)) != -1){
         System.out.print(new String(chars,0,readCounts));
     }
 }catch (Exception e){
     e.printStackTrace();
 }finally {
     try {
         reader.close();
     } catch (IOException e) {
         e.printStackTrace();
     }
 }
java.io.FileWriter(文件字符输入流)
 FileWriter out = null;
 try {
     // 初始化一个文件字符输出流对象
     out = new FileWriter("C:\\Users\\Administrator\\Desktop\\temp03.txt",true); // 不想清空一直累加的话  可以在此处加true
     // 开始写
     char[] chars = {'我','是','中','国','人'};
     // 刷新
     out.write(chars);
     out.write(chars,0,2);
     out.write("我是一名java工程师!");
 }catch (Exception e) {
     e.printStackTrace();
 }finally {
     try {
         out.flush();
         out.close();
     } catch (IOException e) {
         e.printStackTrace();
     }
 }

转换流(将字节流转换成字符流)

  • java.io.InputStreamReader

  • java.io.OutputStreamWriter

缓冲流专属

java.io.BufferedReader,带有缓冲区的字符输入流

使用的时候不需要创建数组了,自带缓冲区

FileReader fileReader = null;
 BufferedReader bufferedReader = null;
  try{
      fileReader = new FileReader("C:\\Users\\Administrator\\Desktop\\temp01.txt");
      // 当一个流的构造方法中需要一个流的时候,这个被传进来的流叫做: 节点流.
      // 外部负责包装的这个流,叫做:包装流,还有一个名字叫做 : 处理流
      // 像当前这个程序来说: FileReader就是一个节点流。BufferedReader就是包装流/处理流。
      bufferedReader = new BufferedReader(fileReader);
      String s ;
      while((s = bufferedReader.readLine())!=null){
          System.out.println(s);
      }
  }catch (Exception e ) {
      e.printStackTrace();
  } finally {
      // 关闭流
      // 对于包装流来说,只需要关闭最外层流就行,里面的节点流会自动关闭!
      try {
          bufferedReader.close();
      } catch (IOException e) {
          e.printStackTrace();
      }
  }
java.io.BufferedWriter,带有缓冲去的字符输出流
BufferedWriter bw = null;
try{
    bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("C:\\Users\\Administrator\\Desktop\\temp04.txt",true)));
    bw.write("hello world");
    bw.write("\n");
    bw.write("xxliao");
}catch (Exception e){
    e.printStackTrace();
}finally {
    try {
        bw.flush();
        // 关闭最外层
        bw.close();
    }catch (Exception e) {
        e.printStackTrace();
    }
}
java.io.BufferedInputStream
java.io.BufferedOutputSteam

数据流专属

java.io.DataInputStream,数据字节写入流

对于DataOutputStream写入的文件,只能使用DataInputStream去读取,并且读的时候需要提前知道写入的顺序,只有写和读取的顺序一致,才能正确取出数据。

 DataInputStream dis = new DataInputStream(new FileInputStream("data"));
      // 开始读
      Byte b = dis.readByte();
      Short s = dis.readShort();
      int i = dis.readInt();
      Float f = dis.readFloat();
      Boolean sex = dis.readBoolean();
      Double d = dis.readDouble();

      System.out.println(b);
      System.out.println(s);
      System.out.println(i);
      System.out.println(f);
      System.out.println(sex);
      System.out.println(d);

java.io.DataOutputStream,数据字节输出流

这个流可以将数据、以及该数据的数据类型一同写入文件,但是这个文件不是普通的文本文件。

 // 创建数据专属的字节输出流
  DataOutputStream dos = new DataOutputStream(new FileOutputStream("data"));
  // 写数据
  byte b =100;
  short s =200;
  int i =300;
  long l = 400L;
  float f =3.0f;
  double d = 3.14;
  boolean sex = false;
  char c = 'a';
  // 写
  dos.writeByte(b);
  dos.writeShort(s);
  dos.writeInt(i);
  dos.writeFloat(f);
  dos.writeBoolean(sex);
  dos.writeDouble(d);
  dos.flush();
  dos.close();

标准输出流

java.io.PrintWriter,标准字节输出流

默认输出到控制台上,也就是System.out.println()方法

PrintStream ps = null;
try {
     // 指向一个日志文件
     ps = new PrintStream(new FileOutputStream("C:\\Users\\Administrator\\Desktop\\log.txt",true));
     // 改变流的输出方向
     System.setOut(ps);
     // 获取系统当前时间
     Date nowTime = new Date();
     // 日期格式化
     SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
     String strTime = sdf.format(nowTime);
     System.out.println(strTime+": "+msg);

 } catch (FileNotFoundException e) {
     e.printStackTrace();
 }finally {
     ps.close();
 }
java.io.PrintStream

对象流

java.io.ObjectInputStream
 ObjectInputStream ois = new ObjectInputStream(new FileInputStream("students"));
  // 开始反序列化  从硬盘中读到内存当中
  Object obj = ois.readObject();
  // 反序列化回来是一个学生对象  所以会调用学生对象的toString方法
  System.out.println(obj);
  ois.close();
  ObjectInputStream oos = new ObjectInputStream(new FileInputStream("users"));
  // 自己测试的时候  用 instanceOf 判断过返回的对象是 list集合
  List<User> userList = (List<User>)oos.readObject();
   for(User user : userList){
       System.out.println(user);
   }
   oos.close();
java.io.ObjectOutputStream
// 实现可序列化的接口 接口中无任何内容 只是一个标志性接口
public class Student implements Serializable {
    /**
     * Java虚拟机看到Serializable接口后,会自动生成一个序列化版本号
     * 这里没有手动写出来,java虚拟机会吗,默认提供这个序列化版本号
     * 建议将序列化版本号写出来,不建议自动生成
     */
    private static  final long serialVersionUID = 1L; // 手动写出序列化版本号
    private int no;
    private String name;

    // 过了很久,Student这个类源代码改动了
    // 源代码改动之后,需要重新编译,编译之后生成了全新的字节码文件。
    // 并且class文件再次运行的时候,java虚拟机生成的序列化版本号也会发生相应的改变。
    private int age;
}

// 创建java对象
 Student s = new Student(111, "张三");
 // 序列化
 ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("students"));
 // 序列化对象
 oos.writeObject(s);
 // 刷新
 oos.flush();
 // 关闭
 oos.close();

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Starry-Leo

帮到了您,有闲钱,再打赏哦~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值