第六章:IO流

第六章:IO流

一:流的划分与简介

1. 什么是流??

I(Input,输入) O(Output,输出)流,是java中用来传输数据的方式。

2. 流的划分

  • 按流向划分:
    输入流:读数据(是将文件或其它输入设备的数据加载到内存的过程)
    输出流:写数据(是将内存中的数据保存到文件或其他输出设备)
    在这里插入图片描述

  • 按操作分:
    字节流:文件通常是由一连串的字节或字符构成,组成文件的字节序列称为字节流(以Stream结尾)。
    字符流:组成文件的字符序列称为字符流(以Reader或者Writer结尾)。
    在这里插入图片描述

3. 四种流的继承结构

  • 字节输入流(InputStream)
    InputStream 是字节输入流,InputStream 是一个抽象类,所有继承了 InputStream 的类都是字节输入流,主要了解以下子类即可:
    在这里插入图片描述
  • 字节输出流(OutputStream)
    所有继承了 OutputStream 都是字节输出流
    在这里插入图片描述
  • 字符输入流(Reader)
    所有继承了 Reader 都是字符输入流
    在这里插入图片描述
  • 字符输出流(Writer)
    所有继承了 Writer 都是字符输出流
    在这里插入图片描述

4. java.io下必须掌握的16种流

  • 文件专属流
    java.io.FileInputStream
    java.io.FileOutputStream
    java.io.FileReader
    java.io.FileWriter
  • 转换流
    java.io.InputStreamReader
    java.io.OutputStreamWriter
  • 缓冲流
    java.io.BufferedInputStream
    java.io.BufferedOutputStream
    java.io.BufferedReader
    java.io.BufferedWriter
  • 数据流专属
    java.io.DataInputStream
    java.io.DataOutputStream
  • 标准输出流
    java.io.PrintWriter
    java.io.PrintStream
  • 对象专属流
    java.io.ObjectInputStream
    java.io.ObjectOutputStream

二:16种流的学习

1. 流中必须注意的两个方法

  • close() 方法: 所有的流(输入和输出)都实现了:java.io.Closeable接口,都是可关闭的。
  • flush() 方法: 所有的输出流都实现了: java.io.Flushable接口,都是可刷新的。

2.文件专属流

  • java.io.FileInputStream

    /*
        java.io.FileInputStream
            1.文件字节输入流,万能的,任何类型的文件都可以采用这个流来读
            2.字节的方式,完成输入操作,完成读的操作(硬盘----》内存)
     */
    
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.IOException;
    
    public class FileInputStreamTest01 {
          
          
        public static void main(String[] args) {
          
          
            //创建文件字节输入流对象
            FileInputStream fis = null;
            try {
          
          
                fis = new FileInputStream("E:\\Workspace\\Study\\javase\\src\\进阶\\IO流06\\temp");
                //开始读 int read() 从此输入流中读取一个数据字节。
                int readData = fis.read();//这个方法的返回值是:读取到的“字节”的本身
                System.out.println(readData);//97
    
                readData = fis.read();
                System.out.println(readData);//98
    
                readData = fis.read();
                System.out.println(readData);//99
    
                readData = fis.read();
                System.out.println(readData);//100
    
                readData = fis.read();
                System.out.println(readData);//101
    
                readData = fis.read();
                System.out.println(readData);//102
                //读到文件的末尾,再也读不到数据,返回-1
                readData = fis.read();
                System.out.println(readData);//-1
    
                readData = fis.read();
                System.out.println(readData);//-1
    
                readData = fis.read();
                System.out.println(readData);//-1
    
            } catch (FileNotFoundException e) {
          
          
                e.printStackTrace();
            } catch (IOException e) {
          
          
                e.printStackTrace();
            } finally {
          
          
                //关闭流的前提是流不是空,流是null没必要关闭
                if (fis != null) {
          
          
                    try {
          
          
                        fis.close();
                    } catch (IOException e) {
          
          
                        e.printStackTrace();
                    }
                }
            }
        }
    }
    
    
    /*
        采用循环方式读取
        分析这个程序的缺点:
            一次读取一个字节byte,这样内存和硬盘交互太频繁,基本上时间/资源都耗费在交互上面了
            能不能一次读取多个字符串呢??可以
     */
    public class FileInputStreamTest02 {
          
          
        public static void main(String[] args) {
          
          
            FileInputStream fis = null;
            try {
          
          
                fis = new FileInputStream("E:\\Workspace\\Study\\javase\\src\\进阶\\IO流06\\temp");
    //            while (true){
          
          
    //                int readData = fis.read();
    //                if (readData == -1){
          
          
    //                    break;
    //                }
    //                System.out.println(readData);
    //            }
                //改造while循环
                int readData = 0;
                while ((readData = fis.read()) != -1){
          
          
                    System.out.println(readData);
                }
            } catch (FileNotFoundException e) {
          
          
                e.printStackTrace();
            } catch (IOException e) {
          
          
                e.printStackTrace();
            } finally {
          
          
                if (fis != null) {
          
          
                    try {
          
          
                        fis.close();
                    } catch (IOException e) {
          
          
                        e.printStackTrace();
                    }
                }
            }
        }
    }
    
    /*
         int read(byte[] b)
         一次读取b.length个字节
         减少硬盘和内存的交互,提高程序的执行效率
     */
    public class FileInputStreamTest03 {
          
          
        public static void main(String[] args) {
          
          
            FileInputStream fis = null;
            try {
          
          
                //相对路径的话呢?相对路径一定是从当前所在的位置作为起点开始找!!
                //idea默认的当前路径在哪??工程Project的跟就是IDEA的当前的路径
                fis = new FileInputStream("E:\\Workspace\\Study\\javase\\src\\进阶\\IO流06\\temp");
                //开始读,采用byte数组,一次读取多个字节。最多读取"数组.length"个字节
                byte[] bytes = new byte[4];
                //这个方法返回值是读取到的字节的数量,不是字节本身
                int readCount = fis.read(bytes);
                System.out.println(readCount);//第一次读到4个字节
                //将字节数组全部转换成字符串
                //System.out.println(new String(bytes));//abcd
                //不应该全部都转换,应该是读取了多少个字节,转换成多少个
                System.out.println(new String(bytes,0,readCount));
    
                readCount = fis.read(bytes);
                System.out.println(readCount);//第二次读到2个字节
                //System.out.println(new String(bytes));//efcd
    
                readCount = fis.read(bytes);//一个字节都没有了,返回-1
                System.out.println(readCount);
            } catch (FileNotFoundException e) {
          
          
                e.printStackTrace();
            } catch (IOException e) {
          
          
                e.printStackTrace();
            } finally {
          
          
                if (fis != null) {
          
          
                    try {
          
          
                        fis.close();
                    } catch (IOException e) {
          
          
                        e.printStackTrace();
                    }
                }
            }
        }
    }
    
    
    public class FileInputStreamTest04 {
          
          
        public static void main(String[] args) {
          
          
            FileInputStream fis = null;
            try {
          
          
                fis = new FileInputStream("E:\\Workspace\\Study\\javase\\src\\进阶\\IO流06\\HelloWorldTest");
                //准备一个byte数组
                byte [] bytes = new byte[4];
                int readCount = 0;
                while ((readCount = fis.read(bytes)) != -1){
          
          
                    System.out.print(new String(bytes,0,readCount));
                }
            } catch (FileNotFoundException e) {
          
          
                e.printStackTrace();
            } catch (IOException e) {
          
          
                e.printStackTrace();
            } finally {
          
          
                if (fis != null) {
          
          
                    try {
          
          
                        fis.close();
                    } catch (IOException e) {
          
          
                        e.printStackTrace();
                    }
                }
            }
        }
    }
    
  • java.io.OutputInputStream

    /*
    FileOutputStream(String name) 这种方式谨慎使用,当没有文件时会新建,每次运行会先将源文件清空然后再写入即
                                (无法对源文件进行追加)
    FileOutputStream(String name, boolean append) //以追加的方式写入
     */
    public class FileOutputStreamTest01 {
          
          
        public static void main(String[] args) {
          
          
            FileOutputStream fos = null;
            try {
          
          
                //当myfile文件不存在的时候,会自动创建
                //这种方式谨慎使用,当没有文件时会新建,每次运行会先将源文件清空然后再写入即(无法对源文件进行追加)
    //            fos = new FileOutputStream("myfile");
                //以追加的方式写入
                fos = new FileOutputStream("myfile",true);
                //开始写
                byte[] bytes = {
          
          97,98,99,100};
                //将byte数组全部写入
                fos.write(bytes);
                //将byte数组一部分写入
                fos.write(bytes,0,2);
                //字符串
                String s = "My name is hanjian";
                byte [] bytes1 = s.getBytes();
                fos.write(bytes1);
                //写完之后一定要刷新
                fos.flush();
            } catch (FileNotFoundException e) {
          
          
                e.printStackTrace();
            } catch (IOException e) {
          
          
                e.printStackTrace();
            } finally {
          
          
                if (fos != null) {
          
          
                    try {
          
          
                        fos.close();
                    } catch (IOException e) {
          
          
                        e.printStackTrace();
                    }
                }
            }
        }
    }
    
  • java.io. FileReader

    /*
        FileReader:
            文本字符输入流,只能读取普通文本
            读取文本内容时,比较方便,快捷
     */
    public class FileReaderTest01 {
          
          
        public static void main(String[] args) {
          
          
            FileReader reader = null;
            try {
          
          
                reader = new FileReader("myfile");
                //开始读
                char [] chars = new char[2];
                int readerCount = 0;
                while ((readerCount = reader.read(chars)) != -1){
          
          
                    System.out.print(new String(chars,0,readerCount));
                }
            } catch (FileNotFoundException e) {
          
          
                e.printStackTrace();
            } catch (IOException e) {
          
          
                e.printStackTrace();
            } finally {
          
          
                if (reader != null) {
          
          
                    try {
          
          
                        reader.close();
                    } catch (IOException e) {
          
          
                        e.printStackTrace();
                    }
                }
            }
        }
    }
    
  • FileWriter

    /*
        FileWriter:
            文件字符输出流,写
            只能输出普通文本。
     */
    public class FileWriterTest01 {
          
          
        public static void main(String[] args) {
          
          
            FileWriter out = null;
            try {
          
          
                out = new FileWriter("myfile",true);
                //开始写
                char[] chars = {
          
          '我','是','中','国','人'};
                out.write(chars);
                
                out.write("hello world");
                out.write("\n");
                out.write("hello world");
                //刷新
                out.flush();
            } catch (IOException e) {
          
          
                e.printStackTrace();
            }finally {
          
          
                if (out != null) {
          
          
                    try {
          
          
                        out.close();
                    } catch (IOException e) {
          
          
                        e.printStackTrace();
                    }
                }
            }
        }
    }
    
    
  • 如何使用FileInputStream + FileOutputStream完成文件的拷贝

    /*
        使用FileInputStream + FileOutputStream完成文件的拷贝。
        拷贝的过程应该是一边读,一边写。
        使用以上的字节流拷贝文件的时候,文件的类型随意
     */
    public class Copy01 {
          
          
        public static void main(String[] args) {
          
          
            FileInputStream fis = null;
            FileOutputStream fos = null;
            try {
          
          
                //创建一个输入流对象
                fis = new FileInputStream("001.qlv");
                //创建一个输出流对象
                fos = new FileOutputStream("002.qlv");
                //核心:一边读,一边写
                byte[] bytes = new byte[1024 * 1024];//1MB
                int readCount = 0;
                while ((readCount = fis.read(bytes)) != -1){
          
          
                    fos.write(bytes,0,readCount);
                }
                fos.flush();
            } catch (FileNotFoundException e) {
          
          
                e.printStackTrace();
            } catch (IOException e) {
          
          
                e.printStackTrace();
            }finally {
          
          
                //分开try
                //一起try的时候可能会导致另一个流的关闭异常
                if (fos != null) {
          
          
                    try {
          
          
                        fos.close();
                    } catch (IOException e) {
          
          
                        e.printStackTrace();
                    }
                }
                if (fis != null) {
          
          
                    try {
          
          
                        fis.close();
                    } catch (IOException e) {
          
          
                        e.printStackTrace();
                    }
                }
            }
        }
    }
    
  • 如何使用FileReader FileWriter完成普通文件的拷贝

    /*
        使用FileReader FileWriter进行拷贝的话,只能拷贝"普通文本"文件
     */
    public class Copy02 {
          
          
        public static void main(String[] args) {
          
          
            FileReader in = null;
            FileWriter out = null;
    
            try {
          
          
                //读
                in = new FileReader("javase\\src\\进阶\\IO流06\\文件专属\\Copy02.java");
                //写
                out = new FileWriter("Copy02.java");
                //一边读一边写
                //先准备个char数组
                char[] chars = new char[1024 * 512];//1MB
                int readCount = 0;
                while ((readCount = in.read(chars)) != -1){
          
          
                    out.write(chars,0,readCount);
                }
                out.flush();
            } catch (FileNotFoundException e) {
          
          
                e.printStackTrace();
            } catch (IOException e) {
          
          
                e.printStackTrace();
            }finally {
          
          
                if (in != null) {
          
          
                    try {
          
          
                        in.close();
                    } catch (IOException e) {
          
          
                        e.printStackTrace();
                    }
                }
                if (out != null) {
          
          
                    try {
          
          
                        out.close();
                    } catch (IOException e) {
          
          
                        e.printStackTrace();
                    }
                }
            }
        }
    }
    

3. 缓冲流和转换流

/*
    BufferedReader:
        带有缓冲区的字符输入流。
        使用这些流的时候不需要自定义char数组,或自定义byte数组。自带缓冲
 */
public class BufferedReaderTest01 {
    
    
    public static void main(String[] args){
    
    
        FileReader reader = null;
        BufferedReader br = null;
        try {
    
    
            reader = new FileReader("Copy02.java");
            //当一个流的构造方法中需要一个流的时候,这个被传进来的流叫做:节点流
            //外部负责包装的这个流叫做:包装流(处理流)
            //向当前的程序来说:FileReader叫做节点流,BufferedReader叫做包装流(处理流)
            br = new BufferedReader(reader);

//        //读一行
//        String firstLine = br.readLine();
//        System.out.println(firstLine);
//
//        //读第二行
//        String secondLine = br.readLine();
//        System.out.println(secondLine);
//
//        //读第三行
//        String thirdLine = br.readLine();
//        System.out.println(thirdLine);
            // br.readLine()放法读取一个文本行,但是它不会将文本的换行符读取进来
            String s = null;
            while ((s = br.readLine()) != null){
    
    
                System.out.println(s);
            }
        } catch (FileNotFoundException e) {
    
    
            e.printStackTrace();
        } catch (IOException e) {
    
    
            e.printStackTrace();
        }finally {
    
    
            if (br != null) {
    
    
                try {
    
    
                    //关闭流
                    br.close();//对于包装流来水,只需要关闭最外层流就行,里面的节点流会自动关闭
                } catch (IOException e) {
    
    
                    e.printStackTrace();
                }

            }
        }
    }
}
/*
    转换流InputStreamReader
 */
public class BufferedReaderTest02 {
    
    
    public static void main(String[] args) throws Exception {
    
    
        /*
        //节点流
        FileInputStream in = new FileInputStream("Copy02.java");
        //通过转换流转换
        //in是节点流,reader是包装流
        InputStreamReader reader = new InputStreamReader(in);
        //reader是节点流,br是包装流
        BufferedReader br = new BufferedReader(reader);
         */
        //合并
        BufferedReader br = new BufferedReader(new InputStreamReader(
                new FileInputStream("Copy02.java")));
        String line = null;
        while ((line = br.readLine())!=null){
    
    
            System.out.println(line);
        }
        br.close();
    }
}

/*
    BufferedWriter:带有缓冲的字符输出流
 */
public class BufferedWriterTest01 {
    
    
    public static void main(String[] args) throws IOException {
    
    
        //BufferedWriter out = new BufferedWriter(new FileWriter("copy"));
        BufferedWriter out = new BufferedWriter(new OutputStreamWriter(
                new FileOutputStream("copy",true)));
        //开始写
        out.write("hello world");
        out.write("\n");
        out.write("hello world");
        //刷新
        out.flush();
        //关闭最外层
        out.close();
    }
}

4. 标准输出流

/*
    java.io.PrintStream:标准的字节输出流。默认输出到控制台上
 */
public class printStream {
    
    
    public static void main(String[] args)throws Exception {
    
    
        //联合起来写
        System.out.println("hello world");
        //分开写
        PrintStream ps = System.out;
        ps.println("hello 111");
        ps.println("hello 222");
        //标准输出流不需要手动close()关闭
        //可以改变标准输出流的输出方向吗??可以

        //标准输出流不在指向控制台,指向"log"文件
        PrintStream printStream = new PrintStream(new FileOutputStream("log"));
        //修改输出方向,将输出方向改到“log”文件
        System.setOut(printStream);
        //再输出
        System.out.println("hello world");
        System.out.println("hello 111");
        System.out.println("hello 222");
    }
}
  • 如何利用标准输出流做一个简单的日志文件

    /*
        日志工具
     */
    public class Logger {
          
          
        public static void log(String msg){
          
          
            /*
                记录日志的方法
             */
            //指向一个日志文件
            PrintStream out = null;
            try {
          
          
                out = new PrintStream(new FileOutputStream("log.txt",true));
                //改变输出方向
                System.setOut(out);
                //日期当前时间
                Date nowTime = new Date();
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss:SSSS");
                String strTime = sdf.format(nowTime);
    
                System.out.println(strTime+":" + msg);
            } catch (FileNotFoundException e) {
          
          
                e.printStackTrace();
            }
        }
    }
    
    
    public class LogTest {
          
          
        public static void main(String[] args) {
          
          
            Logger.log("调用了System类的gc方法,建议启动垃圾回收期回收");
            Logger.log("hello");
            Logger.log("world");
        }
    }
    

5. 数据专属流

  • java.io. DataOutputStream

    /*
        java.io.DataOutputStream:数据专属的流
        这个流可以将数据连同数据的类型一并写入文件
        注意:这个文件不是普通文本文档。
    */
    public class DataOutputStreamTest01 {
          
          
        public static void main(String[] args) throws Exception {
          
          
            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.writeLong(l);
            dos.writeFloat(f);
            dos.writeDouble(d);
            dos.writeBoolean(sex);
            dos.writeChar(c);
            //刷新
            dos.flush();
            //关闭
            dos.close();
        }
    }
    
  • java.io. DataInputStream

    /*
        DataInputStream:数据字节输入流
        DataOutputStream写的文件,只能使用DataInputStream去读。并且读的时候你需要提前知道写入的顺序。
            读的顺序需要和写的顺序一致。才可以正常取出数据。
     */
    public class DataInputStreamTest01 {
          
          
        public static void main(String[] args) throws Exception {
          
          
            DataInputStream dis = new DataInputStream(new FileInputStream("data"));
            //开始读
            byte b = dis.readByte();
            short s = dis.readShort();
            int i = dis.readInt();
            long l = dis.readLong();
            float f = dis.readFloat();
            double d = dis.readDouble();
            boolean sex = dis.readBoolean();
            char c = dis.readChar();
    
            System.out.println(b);
            System.out.println(s);
            System.out.println(i);
            System.out.println(l);
            System.out.println(f);
            System.out.println(d);
            System.out.println(sex);
            System.out.println(c);
    
            dis.close();
        }
    }
    
    

6.对象专属流又称与序列化(ObjectOutputStream)与反序列化(ObjectInputStream)

对象序列化包括如下步骤:
  1) 创建一个对象输出流,它可以包装一个其他类型的目标输出流,如文件输出流;
  2) 通过对象输出流的writeObject()方法写对象。

对象反序列化的步骤如下:
  1) 创建一个对象输入流,它可以包装一个其他类型的源输入流,如文件输入流;
  2) 通过对象输入流的readObject()方法读取对象。
注意事项:

  • 参与序列化和反序列化的对象,必须实现 Serializable接口

  • Serializable接口是什么??有什么作用??

    注意:通过源代码发现, Serializable接口只是一个标志接口
         public interface Serializable {
         }
      这个接口中什么代码都没有。
      那么它起到什么作用呢??
         起到标识作用,标志的作用,java虚拟机看到这个类实现了这个接口,可能会对这个类
      进行特殊待遇。
         Serializable这个接口是给java虚拟机参考的,java虚拟机看到这个接口后,会为该类自
      动生成一个序列化版本号
    
  • 序列化版本号有什么用??

    java语言是采用什么机制来区分类的??
         1. 类名,如果类名不一样肯定不是同一个类
         2. 序列化版本号:如果类名一样,靠的是序列化版本号来区分类
    序列化版本号是用来区分类的。
    
  • 自动生成的版本号有什么缺点??

         这种自动生成的序列化版本的缺点是:一旦代码确定之后,不能进行后续的修改,
         因为只要修改,必然会重新编译,此时会生成全新的序列化版本号,这个时候java会
    认为这是一个全新的类。
    	 如对于student对象可能会发生如下错误:
    	java.io.InvalidClassException: 进阶.IO流06.对象流.Student;
        local class incompatible:
        stream classdesc serialVersionUID = -4362722773073344459,(之后)
        local class serialVersionUID = 9047878168635619625(之前)
    
  • 最终结论:

        凡是一个类实现了Serializable接口,建议给该类提供一个固定不变的序列化版本号。
        这样,以后这个类即使代码修改了,但是版本号不变,java虚拟号会认为是同一个类。
    

序列化与反序列化例子:

  • 序列化(ObjectOutputStream )
    对象序列化包括如下步骤:
      1) 创建一个对象输出流,它可以包装一个其他类型的目标输出流,如文件输出流;
      2) 通过对象输出流的writeObject()方法写对象。

    public class Student implements Serializable {
          
          
        //java虚拟机看到Serializable接口后,会自动生成一个序列化版本号。
        //这里没有手动写出来,java虚拟机默认提供这个序列化版本号
        //建议序列化版本号手动写出来,不建议自动生成
        private static final long serialVersionUID = 1L;//java虚拟机识别一个类的时候先通过类名,如果类名一样,则通过序列化版本号
    
        private int no;
        private String name;
        /*
        过了很久,Student这个类源代码改动了。
        源代码改动之后,需要重新编译,编译之后生成了权限的字节码文件。
        并且class文件再次运行的时候,java虚拟机生成的序列化版本号也会发生相应的改遍。
         */
        private int age;
        private String email;
    
        public Student() {
          
          
        }
    
        public Student(int no, String name) {
          
          
            this.no = no;
            this.name = name;
        }
    
        public int getNo() {
          
          
            return no;
        }
    
        public void setNo(int no) {
          
          
            this.no = no;
        }
    
        public String getName() {
          
          
            return name;
        }
    
        public void setName(String name) {
          
          
            this.name = name;
        }
    
        @Override
        public String toString() {
          
          
            return "Student{" +
                    "no=" + no +
                    ", name='" + name + '\'' +
                    '}';
        }
    }
    
    public class ObjectOutputStreamTest01 {
          
          
        public static void main(String[] args) throws Exception {
          
          
            //创建java对象
            Student s = new Student(111,"zhangsan");//Student对象没改变之前只有no和name
            //序列化
            ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("students"));
            //序列化对象
            oos.writeObject(s);
            //刷新
            oos.flush();
            //关闭
            oos.close();
        }
    }
    

注意:此时会生成一个student文件,这个文件是不可打开的,不是普通文件。

  • 反序列化(ObjectInputStream)
      对象反序列化的步骤如下:
      1) 创建一个对象输入流,它可以包装一个其他类型的源输入流,如文件输入流;
      2) 通过对象输入流的readObject()方法读取对象。

    public class ObjectInputStreamTest01 {
          
          
        public static void main(String[] args) throws Exception{
          
          
            ObjectInputStream ois = new ObjectInputStream(new FileInputStream("students"));
            //开始反序列化,读
            Object obj = ois.readObject();
            //反序列化回来是一个学生对象,所以会调用学生对象的toString方法
            System.out.println(obj);
            ois.close();
        }
    }
    

上面的反序列化无问题:
注意以下事项:如果我们在序列化对象之前没有提供序列化版本号,序列化后的Student文件,也可以参与反序列化,但当我们序列化后,在反序列化之前更改了Student对象的属性内容,则反序列化将失败,因此参与序列化和反序列化的对象必须实现Serializable接口

如何序列化多个多个对象,transient关键字是什么:

  • transient是让参与序列化的对象中的某个属性不参与序列化。(默认的情况下对象的所有属性都是参与序列化的)

  • 如何序列化多个对象??
    将多个对象先存放在集合中,然后序列化集合,但是注意需要的是,一个文件不可以序列化多个集合,只可以序列化一个

  • 参与序列化的集合和对象中都必须实现了 Serializable接口

    public class User implements Serializable {
          
          
        private int no;
        //transient关键字表示游离的不参与序列化
        //private transient String name;
        private  String name;	
        public User() {
          
          
        }
        public User(int no, String name) {
          
          
            this.no = no;
            this.name = name;
        }
        public int getNo() {
          
          
            return no;
        }
        public void setNo(int no) {
          
          
            this.no = no;
        }	
        public String getName() {
          
          
            return name;
        }
        public void setName(String name) {
          
          
            this.name = name;
        }
        @Override
        public String toString() {
          
          
            return "User{" +
                    "no=" + no +
                    ", name='" + name + '\'' +
                    '}';
        }
    }
    
    public class ObjectOutputStreamTest02 {
          
          
        public static void main(String[] args) throws Exception {
          
          
            List<User> userList = new ArrayList<>();
            userList.add(new User(1,"zhangsan"));
            userList.add(new User(2,"lisi"));
            userList.add(new User(3,"wangwu"));
            ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("users"));
            //序列化一个集合
            oos.writeObject(userList);
            oos.flush();
            oos.close();
        }
    }
    
    public class ObjectInputStreamTest02 {
          
          
        public static void main(String[] args) throws Exception {
          
          
            ObjectInputStream ois = new ObjectInputStream(new FileInputStream("users"));
            Object obj = ois.readObject();
            System.out.println(obj instanceof List);
            List<User> userList = (List<User>)obj;
            for (User user:userList){
          
          
                System.out.println(user);
            }
            ois.close();
        }
    }
    

猜你喜欢

转载自blog.csdn.net/qq_28384023/article/details/109714149