• java编程基础总结——27.IO流


    一、IO流概念
        

    1. 什么是IO流:

    input output stream:输入输出流

    计算数据是在cpu,有cpu两大功能:运算器和控制器。但是cpu不能存储数据,数据存在存储设备,如磁盘、硬盘、U盘、光盘,才能永久存储数据,需要将数据计算之后由cpu运算到磁盘上,会用到IO流;同样的,要计算某个数据,需要将数据先传到cpu中,也要用到IO流

    1)、从狭义上来说:数据在内存中输入和输出     

            将数据提前缓存,加快程序的运行

            代码包括操作系统,普通应用层软件,jvm,都是在在内存中运行

    2)、从广义来说,不同电脑之间的数据流动,(借助网络设备)也是一种IO流
            
    狭义上的IO流:本地进程间的数据流动 (同一个台电脑,不同元器件之间的流动)
    广义上的IO流:远程进程间的数据流动 (不同电脑)

        
    2. IO流的分类:

    1)、流的流动方法(数据的传输方向)站在内存的角度
            |-- 输入流              如将数据从磁盘读到内存
            |-- 输出流              如将计算好的数据存到磁盘上(内存读到磁盘上)

    2)、流的数据格式
            |-- 字节流            (二进制形式) 所有都能用
            |-- 字符流            (二进制效率差,比如一句话,按照字节去翻译就很长)注意:不是所有的                                       流都能用字符流,如一张图片,字符串适用于肉眼能看到的符号

    3)、流的主要作用


            |-- 节点流
            |-- 装饰流(过滤流)装饰节点流
        

    4)、转换流         

         转换字节和字符流的特殊流

    二、字节流

    字节流:
        |-- InputStream           输入流
        |-- OutputStream        输出流

    字符流:
        |-- Reader                   输入流
        |-- Writer                     输出流

    字节流
        装饰流
        数据流
        字符流
        对象流
        对象序列化
        转换流

        

    字节流:

        输入流:

        输出流:

    示例:

    存在bug,读整个字符数组不合适,应该给多少位读多少位。不能保证刚好就是1024,会出现多读的情况

    对比原代码,程序本来到红色的部分已经结束了,但是控制台却多输出了很多其他的代码(绿色部分及之后未展示出来的结果)显然不对.读满了会重复去读

    1. @Test
    2. void testIStream01() {
    3. InputStream is = null;
    4. try {
    5. is = new FileInputStream(new File("D:\\javaSE\\eclipse\\code\\classDemo\\src\\com\\openlab\\demo02\\TestFile.java"));
    6. //read()方法是一次读尽数据,若文件很大,内存是有限的,所以不建议
    7. //所以做一个字节数组
    8. //也可以是1024*4,文件存在磁盘上,是以页存储,一个页是1024*4
    9. //返回int值,-1表示读到末尾
    10. byte[] buf = new byte[1024];
    11. while(is.read(buf) != -1) {
    12. System.out.write(buf);
    13. //println是输出字符串,不能用,操作不了,这里是字节数组
    14. }
    15. } catch (FileNotFoundException e) {
    16. e.printStackTrace();
    17. } catch (IOException e) {
    18. e.printStackTrace();
    19. } finally {
    20. // 关闭流
    21. if (is != null) {
    22. try {
    23. is.close();
    24. } catch (IOException e) {
    25. e.printStackTrace();
    26. }
    27. }
    28. }

    我们将读取的字节数记录下来,只要没读到末尾,一直循环,从0读到记录的位置,这样就可以避免上述情况的发生

    1. @Test
    2. void testIStream02() {
    3. InputStream is = null;
    4. try {
    5. is = new FileInputStream(new File("D:\\javaSE\\eclipse\\code\\classDemo\\src\\com\\openlab\\demo02\\TestFile.java"));
    6. byte[] buf = new byte[1024];
    7. int len = 0;//记录读的字节数
    8. while((len = is.read(buf)) != -1) {
    9. System.out.write(buf, 0, len);
    10. }
    11. } catch (FileNotFoundException e) {
    12. e.printStackTrace();
    13. } catch (IOException e) {
    14. e.printStackTrace();
    15. } finally {
    16. // 关闭流
    17. if (is != null) {
    18. try {
    19. is.close();
    20. } catch (IOException e) {
    21. e.printStackTrace();
    22. }
    23. }
    24. }
    25. }

    1. InputStream    OutputStream的子类

    1)、FileInputStream 字节输入流

    1. @Test
    2. void test01() {
    3. InputStream is = null;
    4. try {
    5. // 1、创建一个输入流对象(XXX数据流)
    6. is = new FileInputStream("a.txt");
    7. // 创建字节数组,通过字节数组读取数据
    8. byte[] buf = new byte[1024];
    9. int len = 0;
    10. while ((len = is.read(buf)) != -1) {
    11. System.out.write(buf, 0, len);//从buf中读,从第0个读len长度
    12. }
    13. } catch (FileNotFoundException e) {
    14. e.printStackTrace();
    15. } catch (IOException e) {
    16. e.printStackTrace();
    17. } finally {
    18. // 一定要注意:流必须关闭
    19. if (is != null) {
    20. try {
    21. is.close();
    22. } catch (IOException e) {
    23. e.printStackTrace();
    24. }
    25. }
    26. }
    27. }

     若是带一次的代码,不用len记录,直接读。会导致字节数组读不满,打出空格(byte[] 默认初始化为0)

    1. @Test
    2. void test01() {
    3. InputStream is = null;
    4. try {
    5. // 1、创建一个输入流对象(XXX数据流)
    6. is = new FileInputStream("a.txt");
    7. // 创建字节数组,通过字节数组读取数据
    8. byte[] buf = new byte[1024];
    9. while ((len = is.read(buf)) != -1) {
    10. System.out.write(buf);//从buf中读,从第0个读len长度
    11. }
    12. } catch (FileNotFoundException e) {
    13. e.printStackTrace();
    14. } catch (IOException e) {
    15. e.printStackTrace();
    16. } finally {
    17. // 一定要注意:流必须关闭
    18. if (is != null) {
    19. try {
    20. is.close();
    21. } catch (IOException e) {
    22. e.printStackTrace();
    23. }
    24. }
    25. }
    26. }

      

    读字符串时,可以用System.out.println()。(借助字符串对象,将字节数组构造为字符串对象)

    1. @Test
    2. void test02() {
    3. InputStream is = null;
    4. try {
    5. // 1、创建一个输入流对象(XXX数据流)
    6. is = new FileInputStream("a.txt");
    7. // 创建字节数组,通过字节数组读取数据
    8. byte[] buf = new byte[1024];
    9. int len = 0;
    10. while ((len = is.read(buf)) != -1) {
    11. // 借助字符串对象,将字节数组构造为字符串对象
    12. String str = new String(buf, 0, len);
    13. System.out.println(str);
    14. }
    15. } catch (FileNotFoundException e) {
    16. e.printStackTrace();
    17. } catch (IOException e) {
    18. e.printStackTrace();
    19. } finally {
    20. // 一定要注意:流必须关闭
    21. if (is != null) {
    22. try {
    23. is.close();
    24. } catch (IOException e) {
    25. e.printStackTrace();
    26. }
    27. }
    28. }
    29. }

    2)、FileOutputStream  字节输出流

    1. @Test
    2. void test03() {
    3. String msg = "你好啊";
    4. FileOutputStream fos = null;
    5. try {
    6. fos = new FileOutputStream(new File("b.txt"));
    7. // 直接将数据一次写入进去(只适用于比较少,下面的例子时拷贝文件,则必须定义字节数组了)
    8. fos.write(msg.getBytes());
    9. System.out.println("写入数据成功!!");
    10. } catch (FileNotFoundException e) {
    11. e.printStackTrace();
    12. } catch (IOException e) {
    13. e.printStackTrace();
    14. } finally {
    15. if (fos != null) {
    16. try {
    17. fos.close();
    18. } catch (IOException e) {
    19. e.printStackTrace();
    20. }
    21. }
    22. }
    23. }

     3)综合

    字节输入流,字节输出流(以文件输入流,文件输出流为例)来拷贝文件

    1. @Test
    2. void test04() {
    3. FileInputStream fis = null;
    4. FileOutputStream fos = null;
    5. try {
    6. // 使用输入流读取数据
    7. fis = new FileInputStream("D:\\javaSE\\note\\第23天笔记.txt");
    8. fos = new FileOutputStream(new File("c:\\a.txt"));
    9. // 一定要通过字节数组进行读取和写入
    10. // 防止内存过大,导致出现OOM
    11. byte[] buf = new byte[1024];
    12. int len = 0;
    13. while((len = fis.read(buf)) != -1) {
    14. fos.write(buf, 0, len);
    15. }
    16. System.out.println("写入数据成功!!");
    17. } catch (FileNotFoundException e) {
    18. e.printStackTrace();
    19. } catch (IOException e) {
    20. e.printStackTrace();
    21. } finally {
    22. if (fis != null) {
    23. try {
    24. fis.close();
    25. } catch (IOException e) {
    26. e.printStackTrace();
    27. }
    28. }
    29. if (fos != null) {
    30. try {
    31. fos.close();
    32. } catch (IOException e) {
    33. e.printStackTrace();
    34. }
    35. }
    36. }
    37. }

    2. 装饰流:

    又被称为过滤流,这种流不能直接使用,主要的作用就是用来装饰节点流(各种可以直接使用流)。如果节点流读取数据比较慢,使用装饰流做缓冲
     


        FilterInputStream是个普通类,但是一般使用它的子类,BufferedInputStream

    装饰流,本质就是一种装饰者设计模式的体现。对原有对象的功能进一步的装饰增强。

    GOF 23中设计模式:
        |-- 单例设计模式(对象不需要多个)节约内存,避免频繁创建对象。加快效率
        |-- 装饰者设计

    1)、BufferedInputStream 

    案列:

    1. @Test
    2. void test05() {
    3. BufferedInputStream bis = null;
    4. BufferedOutputStream bos = null;
    5. try {
    6. //装饰流装饰节点流,所以需要传一个节点流
    7. bis = new BufferedInputStream(new FileInputStream("G:\\windows 系统\\CentOS-7-x86_64-DVD-1810.iso"));
    8. bos = new BufferedOutputStream(new FileOutputStream(new File("c:\\a.iso")));
    9. byte[] buf = new byte[1024*8];
    10. int len = 0;
    11. while ((len = bis.read(buf)) != -1) {
    12. bos.write(buf, 0, len);
    13. }
    14. System.out.println("文件拷贝成功!!");
    15. } catch (FileNotFoundException e) {
    16. e.printStackTrace();
    17. } catch (IOException e) {
    18. e.printStackTrace();
    19. } finally {
    20. if (bis != null) {
    21. try {
    22. bis.close();
    23. } catch (IOException e) {
    24. e.printStackTrace();
    25. }
    26. }
    27. if (bos != null) {
    28. try {
    29. bos.close();
    30. } catch (IOException e) {
    31. e.printStackTrace();
    32. }
    33. }
    34. }
    35. }

    如果不关闭流:

    文件少了,且拷贝的图片下面部分是灰色的

    满了才会将缓冲区的数据刷进去,但是最后一次不一定满,可能把之前的数据拿过来,数据出问题

    不满数字是0,0在颜色里面表示为黑色

    1. @Test
    2. void test06() {
    3. BufferedInputStream bis = null;
    4. BufferedOutputStream bos = null;
    5. try {
    6. bis = new BufferedInputStream(new FileInputStream("c:\\a.jpg"));
    7. bos = new BufferedOutputStream(new FileOutputStream(new File("c:\\b.jpg")));
    8. byte[] buf = new byte[1024];
    9. int len = 0;
    10. while ((len = bis.read(buf)) != -1) {
    11. bos.write(buf, 0, len);
    12. }
    13. System.out.println("文件拷贝成功!!");
    14. } catch (FileNotFoundException e) {
    15. e.printStackTrace();
    16. } catch (IOException e) {
    17. e.printStackTrace();
    18. } finally {
    19. }
    20. }

    如果不关闭,我们可以利用flush()方法,强制刷新,将缓冲池的东西清到目的地

    但是不建议直接手动刷新,建议关闭流。

    缓存流,必须要关闭,因为JVM在缓存流关闭时,将最后数据完成自动刷新

    节点流也需要关闭,因为操作的是一个具体的文件,你一旦占用不关闭,别人就操作不了。比如打开一个文件,此时删除这个文件是删除不掉的

     

    1. @Test
    2. void test06() {
    3. BufferedInputStream bis = null;
    4. BufferedOutputStream bos = null;
    5. try {
    6. bis = new BufferedInputStream(new FileInputStream("c:\\a.jpg"));
    7. bos = new BufferedOutputStream(new FileOutputStream(new File("c:\\b.jpg")));
    8. byte[] buf = new byte[1024];
    9. int len = 0;
    10. while ((len = bis.read(buf)) != -1) {
    11. bos.write(buf, 0, len);
    12. }
    13. // 当代码执行到这儿的时候,读取完成
    14. // 如果最后一次数据没有读取完成,则可以手动刷新缓冲区
    15. // bos.flush();
    16. System.out.println("文件拷贝成功!!");
    17. } catch (FileNotFoundException e) {
    18. e.printStackTrace();
    19. } catch (IOException e) {
    20. e.printStackTrace();
    21. } finally {
    22. // 缓存流,必须要关闭,因为JVM在缓存流关闭时,将最后数据完成自动刷新
    23. if (bis != null) {
    24. try {
    25. bis.close();
    26. } catch (IOException e) {
    27. e.printStackTrace();
    28. }
    29. }
    30. if (bos != null) {
    31. try {
    32. bos.close();
    33. } catch (IOException e) {
    34. e.printStackTrace();
    35. }
    36. }
    37. }
    38. }

    2)、DataOutputStream   DataInputStream 

    数据流

    特殊的装饰流

    引入:存入数字

    1. @Test
    2. void test07() throws Exception {
    3. FileOutputStream fis = new FileOutputStream("a.dat");
    4. int msg = 100;
    5. //fis.write(int b),这个方法是记录读了多少次,并不能存int数据
    6. // String str = Integer.valueOf(msg).toString();先转成包装类,再转成字符串
    7. // fis.write(str.getBytes());利用之前示例过的方法,转成字节数组
    8. // 也可以这样完成转换
    9. fis.write((msg + "").getBytes());
    10. fis.close();
    11. }

    但是这样存储也有问题,比如将msg的值放大

    我们知道int只占4个字节,但是转成字符串就是一个符号占一个字节,所以就是7个字节了

    我们可以用DataOutputStream来解决这个问题

    数据流的使用:
            我们之前讲解的流,如果要保存数字,只要将数字转换为字符串,也就是说
            以字符流的形式保存数据,这样有时候并不是我们需要的,我们有时候就是
            需要以字节保存数据,因此就可以使用数据流来包装文件流完成。

    int msg = 1000000;

     

    1. @Test
    2. void test08() throws Exception {
    3. int msg = 1000000;
    4. DataOutputStream dos = new DataOutputStream(new FileOutputStream("a.dat"));
    5. dos.writeInt(msg);
    6. dos.writeInt(100);
    7. dos.writeInt(10000);
    8. dos.writeInt(123456);
    9. dos.close();
    10. }

     DataInputStream :

    读int值:

    1. @Test
    2. void test09() throws Exception {
    3. DataInputStream dis = new DataInputStream(new FileInputStream("a.dat"));
    4. System.out.println(dis.readInt());
    5. System.out.println(dis.readInt());
    6. System.out.println(dis.readInt());
    7. System.out.println(dis.readInt());
    8. dis.close();
    9. }

    如果再读会抛错

     读long值:

    1. @Test
    2. void test10() throws Exception {
    3. long msg = 1000000000L;
    4. DataOutputStream dos = new DataOutputStream(new FileOutputStream("b.dat"));
    5. dos.writeLong(msg);
    6. dos.close();
    7. }

    用int读long 数据会返回0

    1. @Test
    2. void test11() throws Exception {
    3. DataInputStream dis = new DataInputStream(new FileInputStream("b.dat"));
    4. System.out.println(dis.readInt());
    5. dis.close();
    6. }

     用long读long 结果正常

    1. @Test
    2. void test11() throws Exception {
    3. DataInputStream dis = new DataInputStream(new FileInputStream("b.dat"));
    4. System.out.println(dis.readLong());
    5. dis.close();
    6. }

    三、字符流


    字符流:
        计算机底层使用的二进制数据(字节数据)。所以计算机中都可以用字节去操作,字节流是计        算机最核心的流,但是速度慢。在开发过程中,若是字符串,就非常慢
        字符流是为了加快流的操作,而设计的专门用来操作字符串的一种流。

        注意:字符流 字符串存在编码问题,需要保证在读取和写入时,保持一致!!!(在Ascll码中                 的不影响)

                    字节流无编码问题(二进制)

        
    字符输入流:
            Reader(抽象类),使用的时候应该使用它的子类

    字符串输出流:
            Writer(抽象类)

    字符装饰流:
        BufferedReader        是Reader的子类
        BufferedWriter           是Writer的子类
        PrintWriter    更推荐使用这个打印输出流

    字符输入流例:

    1. @Test
    2. void test01() {
    3. Reader reader = null;
    4. try {
    5. reader = new FileReader(new File("D:\javaSE\eclipse\code\classDemo\src\com\openlab\demo02\TestFile.java"));
    6. char[] buf = new char[1024];
    7. int len = 0;
    8. while((len = reader.read(buf)) != -1) {
    9. System.out.println(String.valueOf(buf, 0, len));
    10. //valueOf支持字符数组,不支持字节数组
    11. }
    12. } catch (FileNotFoundException e) {
    13. e.printStackTrace();
    14. } catch (IOException e) {
    15. e.printStackTrace();
    16. } finally {
    17. if (reader != null) {
    18. try {
    19. reader.close();
    20. } catch (IOException e) {
    21. e.printStackTrace();
    22. }
    23. }
    24. }
    25. }

    字符输出流例:

    1. @Test
    2. void test02() {
    3. Reader reader = null;
    4. Writer writer = null;
    5. try {
    6. reader = new FileReader(new File("D:\javaSE\eclipse\code\classDemo\src\com\openlab\demo02\TestFile.java"));
    7. writer = new FileWriter("c:\\a.java");
    8. char[] buf = new char[1024];
    9. int len = 0;
    10. while((len = reader.read(buf)) != -1) {
    11. writer.write(buf, 0, len);
    12. }
    13. System.out.println("拷贝文件成功");
    14. } catch (FileNotFoundException e) {
    15. e.printStackTrace();
    16. } catch (IOException e) {
    17. e.printStackTrace();
    18. } finally {
    19. if (reader != null) {
    20. try {
    21. reader.close();
    22. } catch (IOException e) {
    23. e.printStackTrace();
    24. }
    25. }
    26. if (writer != null) {
    27. try {
    28. writer.close();
    29. } catch (IOException e) {
    30. e.printStackTrace();
    31. }
    32. }
    33. }
    34. }

     BufferedReader :

    1. @Test
    2. void test03() {
    3. BufferedReader br = null;
    4. try {
    5. br = new BufferedReader(new FileReader(new File("D:\\javaSE\\eclipse\\code\\classDemo\\src\\com\\openlab\\demo02\\TestFile.java")));
    6. String msg = null;
    7. // 字符输入流,可以使用装饰流,按行读取
    8. while ((msg = br.readLine()) != null) {
    9. System.out.println(msg);
    10. }
    11. } catch (FileNotFoundException e) {
    12. e.printStackTrace();
    13. } catch (IOException e) {
    14. e.printStackTrace();
    15. } finally {
    16. if (br != null) {
    17. try {
    18. br.close();
    19. } catch (IOException e) {
    20. e.printStackTrace();
    21. }
    22. }
    23. }
    24. }

    BufferedWriter:

    1. @Test
    2. void test04() {
    3. BufferedReader br = null;
    4. BufferedWriter bw = null;
    5. try {
    6. br = new BufferedReader(new FileReader(new File("D:\\javaSE\\eclipse\\code\\classDemo\\src\\com\\openlab\\demo02\\TestFile.java")));
    7. bw = new BufferedWriter(new FileWriter("d:\\a.java"));
    8. String msg = null;
    9. // 字符输入流,可以使用装饰流,按行读取
    10. while ((msg = br.readLine()) != null) {
    11. // bw.write(msg);
    12. // 我们可以手动添加换行符
    13. bw.write(msg + "\n");
    14. }
    15. } catch (FileNotFoundException e) {
    16. e.printStackTrace();
    17. } catch (IOException e) {
    18. e.printStackTrace();
    19. } finally {
    20. if (br != null) {
    21. try {
    22. br.close();
    23. } catch (IOException e) {
    24. e.printStackTrace();
    25. }
    26. }
    27. if (bw != null) {
    28. try {
    29. bw.close();
    30. } catch (IOException e) {
    31. e.printStackTrace();
    32. }
    33. }
    34. }
    35. }

    PrintWriter:

    1. @Test
    2. void test05() {
    3. BufferedReader br = null;
    4. PrintWriter out = null;
    5. try {
    6. br = new BufferedReader(new FileReader(new File("D:\\javaSE\\eclipse\\code\\classDemo\\src\\com\\openlab\\demo02\\TestFile.java")));
    7. out = new PrintWriter("d:\\a.java");
    8. String msg = null;
    9. // 字符输入流,可以使用装饰流,按行读取
    10. while ((msg = br.readLine()) != null) {
    11. out.println(msg);
    12. }
    13. } catch (FileNotFoundException e) {
    14. e.printStackTrace();
    15. } catch (IOException e) {
    16. e.printStackTrace();
    17. } finally {
    18. if (br != null) {
    19. try {
    20. br.close();
    21. } catch (IOException e) {
    22. e.printStackTrace();
    23. }
    24. }
    25. if (out != null) {
    26. out.close();
    27. }
    28. }
    29. }

    总结:
        |-- 字符缓存流完成字符的操作
            通过行来读取和写入字符串,所以字符流建议带上装饰流(能按行读取)
            |-- 字符串输入缓存流
                BufferedReader
            |-- 字符串输出缓存流
                BufferedWriter
                不太推荐大家使用BufferedWriter,因为需要手动添加换行符(按行读取,readLine找到\n              就解析了,能把数据写进去,但是最终结果是不会换行)
                推荐使用打印输出流(节点流)
                PrintWriter
                    |-- print()
                    |-- println()
        

    四、转换流:

    将字节流转换为字符流操作

    读取的是字节数据,一般是文本数据(字符串数据)为了加快效率,可以转成字符流

    如控制台的标准输入流是字节流,直接转流类型不匹配。BufferedReader只能接受Reader

     

        InputStreamReader        Reader的子类
        OuputStreamWriter        Writer的子类

     InputStreamReader       可以做一个简单人工智能

    1. @Test
    2. void test01() throws IOException {
    3. BufferedReader br = null;
    4. // InputStreamReader 转换流
    5. // 可以将字节输入流转换为字符输入流
    6. br = new BufferedReader(new InputStreamReader(System.in));
    7. String str = null;
    8. while ((str = br.readLine()) != null) {
    9. if (str.equalsIgnoreCase("exit"))
    10. break;
    11. System.out.println(str.replace("吗?", ""));
    12. }
    13. br.close();
    14. }

     

    1. @Test
    2. void test02() throws IOException {
    3. BufferedReader br = null;
    4. PrintWriter out = null;
    5. br = new BufferedReader(new InputStreamReader(System.in));
    6. out = new PrintWriter(new OutputStreamWriter(new FileOutputStream("d:\\a.html")));
    7. String str = null;
    8. while ((str = br.readLine()) != null) {
    9. if (str.equalsIgnoreCase("exit"))
    10. break;
    11. out.println(str);
    12. }
    13. br.close();
    14. out.close();
    15. }

    五、对象流

    对象流:
        对象本质:它是一个抽象概念,是JVM中的一种虚拟出来的抽象概念
                           在jvm中,通过new 关键字,配合class类,就可以构造一个java对象

        
        对象流就是java提供一种,可以将java对象这种虚拟的概念转换为
        一种物理可以存储或者传输的真实数据。

        将虚拟的JVM中的对象转换为字节数据

    String实现了Serializable接口,可以直接用

    1. @Test
    2. void test01() {
    3. String msg = "你好";
    4. ObjectOutputStream oos = null;
    5. try {
    6. oos = new ObjectOutputStream(new FileOutputStream("c:\\info.dat"));
    7. oos.writeObject(msg);
    8. System.out.println("对象保存成功");
    9. } catch (IOException e) {
    10. e.printStackTrace();
    11. } finally {
    12. if (oos != null) {
    13. try {
    14. oos.close();
    15. } catch (IOException e) {
    16. e.printStackTrace();
    17. }
    18. }
    19. }
    20. }
    1. @Test
    2. void test02() {
    3. ObjectInputStream ois = null;
    4. try {
    5. ois = new ObjectInputStream(new FileInputStream("c:\\info.dat"));
    6. // Object msg = ois.readObject();不强转
    7. String msg = (String) ois.readObject();//刚刚存的字符串,知道数据类型,所以直接强转了
    8. System.out.println(msg);
    9. } catch (IOException e) {
    10. e.printStackTrace();
    11. } catch (ClassNotFoundException e) {
    12. e.printStackTrace();
    13. } finally {
    14. if (ois != null) {
    15. try {
    16. ois.close();
    17. } catch (IOException e) {
    18. e.printStackTrace();
    19. }
    20. }
    21. }
    22. }

    对象序列化: 

    1. @Test
    2. void test03() {
    3. Person p1 = new Person(1, "张三", "法外狂徒", "男", 30);
    4. ObjectOutputStream oos = null;
    5. try {
    6. oos = new ObjectOutputStream(new FileOutputStream("c:\\info.dat"));
    7. oos.writeObject(p1);
    8. System.out.println("对象保存成功");
    9. } catch (IOException e) {
    10. e.printStackTrace();
    11. } finally {
    12. if (oos != null) {
    13. try {
    14. oos.close();
    15. } catch (IOException e) {
    16. e.printStackTrace();
    17. }
    18. }
    19. }
    20. }

     对象反序列化:

    1. @Test
    2. void test04() {
    3. ObjectInputStream ois = null;
    4. try {
    5. ois = new ObjectInputStream(new FileInputStream("c:\\info.dat"));
    6. Person p1 = (Person) ois.readObject();
    7. System.out.println(p1);
    8. } catch (IOException e) {
    9. e.printStackTrace();
    10. } catch (ClassNotFoundException e) {
    11. e.printStackTrace();
    12. } finally {
    13. if (ois != null) {
    14. try {
    15. ois.close();
    16. } catch (IOException e) {
    17. e.printStackTrace();
    18. }
    19. }
    20. }
    21. }

     

     

    1. 对象序列化:

    Serialize:将虚拟对象转换为一种可以直接传输或者保存到数据(字节、字符)过程

    2. 对象反序列化:

    将序列化后的字节或者字符数据重新转换为对象,对象反序列化

    3. 对象持久化:

    将数据永久保存(可以通过IO、数据库)

    java官方提供的序列化,是将java对象转换为字节数据。
    注意:java的对象要实现序列化和反序列化,必须实现Serializable(这个标记接口)

            
    4. transient关键字

     transient:被这个关键字修饰的属性,无法被持久化。

        运算过程中临时使用的,不需要记录值

    例:

    将Person的gender用transient关键字修饰,之后重新将数据序列号、持久化(Test03)。

    之后反持久化,反序列化(Test04)

    private transient String gender;

     

    在持久化的时候没有将gender持久化,所以读不到,赋了默认值(String是对象,默认值为null)

  • 相关阅读:
    Centos设置nginx开机自启动设置
    C中volatile总结
    『百日百题 · 基础篇』备战面试,坚持刷题 第四话——循环语句!
    ResultMap详解(处理字段名和属性名不一致)
    Webpack-入门
    Linux常用命令——bye命令
    url请求头信息
    Kafka是如何保证消息不丢失
    Linux操作系统~进程地址空间
    深入了解HTTP与HTTPS关键差异与底层原理
  • 原文地址:https://blog.csdn.net/m0_58679504/article/details/126278407