如何高效的使用IO流?字节流字符流缓冲流序列化对象流打印流全整理

Posted chenry777

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何高效的使用IO流?字节流字符流缓冲流序列化对象流打印流全整理相关的知识,希望对你有一定的参考价值。

字节流字节流字符流字符流
字节输入流字节输出流字符输入流字符输出流
InputStream (抽象类)OutputStream (抽象类)Reader (抽象类)Writer (抽象类)
FileInputStream (实现类,低级流,原始流)FileOutputStream (实现类,低级流,原始流)FileReader (实现类,低级流,原始流)FileWriter (实现类,低级流,原始流)
BufferedInputStream(实现类,缓冲流)BufferedOutputStream(实现类,缓冲流)BufferedReader(实现类,缓冲流)BufferedWriter(实现类,缓冲流)
InputStreamReader(字符输入转换流)OutputStreamWriter(字符输出转换流)
ObjectInputStream(对象字节输入流)ObjectOutputStream(对象字节输出流)

一、按序从文件中读字节

一个个从文件中读

		// 1.创建文件对象定位dlei01.txt
        File file = new File("xxx.txt");
        // 2.创建一个字节输入流管道与源文件接通
        InputStream is = new FileInputStream(file);
        // 4.使用while读取字节数
        // 定义一个整数变量存储字节
        int ch = 0 ;
        while((ch = is.read())!= -1){
            System.out.print((char) ch);
        }
        is.close();

一次读n个字节,最后一次读多少就输出多少

        // 3.简化写法:直接创建一个字节输入流管道与源文件路径接通。
        InputStream is = new FileInputStream("xxxx.txt");
        // a.定义一个字节数组代表桶   // ooo ooo o
        byte[] buffer = new byte[n];
        int len ; // 存储每次读取的字节数。
        while((len = is.read(buffer)) != -1){
            // 读取了多少就倒出多少!
            String rs = new String(buffer , 0 , len);
            System.out.print(rs);
        }
        is.close();

以上2种形式均无法解决中文读取输出乱码的问题,如何通过字节流解决中文输出乱码问题?

定义一个字节数组与文件的大小刚刚一样大,然后一桶水读取全部字节数据再输出!

但是如果读取的文件过大,会出现内存溢出(OutOfMemoryError())

        // 0.定位文件对象
        File f = new File("xxxx.txt");
        // 1.定义一个字节输入流通向源文件路径,简化写法!
        InputStream is = new FileInputStream(f);

        // 2.定义一个字节数组与文件的大小刚刚一样大
        System.out.println("文件大小:"+f.length());
        byte[] buffer = new byte[(int) f.length()];
        int len = is.read(buffer);
        System.out.println("读取了:"+len);
        String rs = new String(buffer);
        System.out.println(rs);
        is.close();

jdk1.9以上,还可以用官方提供的api,其实现逻辑和上面类似

		// 0.定位文件对象
        File f = new File("xxxx.txt");
        // 1.定义一个字节输入流通向源文件路径,简化写法!
        InputStream is = new FileInputStream(f);
	
        // jdk1.9提供readAllBytes()
        byte[] buffer = is.readAllBytes();
        String rs = new String(buffer);
        System.out.println(rs);
        is.close();

但是byte[n]的最大长度是受限的,n<=Integer.MAX_VALUE,所以字节流不太适合用来读中文字符,也就引出了字符流。 在字节流里还有一块字节输出流,下面先介绍字节输出流。

二、按序向文件中写字节

字节输出流:以内存为基准,把内存中的数据,按照字节的形式写出到磁盘文件中去。简单来说,把内存数据按照字节写出到磁盘文件中去。

构造器:

public FileOutputStream(File file):创建一个字节输出流管道通向目标文件对象。
public FileOutputStream(String file):创建一个字节输出流管道通向目标文件路径。
public FileOutputStream(File file , boolean append):创建一个追加数据的字节输出流管道通向目标文件对象。
public FileOutputStream(String file , boolean append):创建一个追加数据的字节输出流管道通向目标文件路径。

方法:

public void write(int a):写一个字节出去 。
public void write(byte[] buffer):写一个字节数组出去。
public void write(byte[] buffer , int pos , int len):写一个字节数组的一部分出去。
[参数一,字节数组;参数二:起始字节索引位置,
参数三:写多少个字节数出去。]

小贴士:

io流在写出的时候,每次新建流管道的时候(new FileOutputStream(“filepath”)) ,会把之前的文件内容覆盖,即默认是覆盖管道;如果需要启动append模式,只需要在构造器的第二个参数加"true"即可

下面来看一些代码实例:

写一个字节出去

		1.创建一个字节输出流管道与目标文件路径接通
		// 文件不存在,默认会自动创建文件
        FileOutputStream os = new FileOutputStream("xxxx.txt");
        // 2.写数据出去
        // a.写一个字节出去
        // 字符和int整型可以自动转换
        os.write(97); // 字节a
        os.write('b'); // 字节b
        // os.write('澳') // [ooo] 只会写出中文的第一个字节,写出去就乱码
        os.flush(); // 立即刷新数据到文件中去,刷新后管道可以继续使用 	
        os.close(); // 关闭资源管道,关闭包含了刷新,关闭后管道不能使用了

写一个字节数组出去

        byte[] bytes = new byte[]{48,49,50,56,56,54,59};
        os.write(bytes);
        // 默认以当前代码编码UTF-8提取字节数组
        byte[] bytes1 = "Java是最优美的语言 · 我爱Java!".getBytes();
        //byte[] bytes2 = "Java是最优美的语言 · 我爱Java!".getBytes("GBK"); // 指定编码方式获取字节数组
        os.write(bytes1);
        
        os.flush(); // 立即刷新数据到文件中去,刷新后管道可以继续使用 	
        os.close(); // 关闭资源管道,关闭包含了刷新,关闭后管道不能使用了

写一个字节数组的一部分出去

		byte[] bytes2 = "Java是最优美的语言".getBytes();
        os.write(bytes2,0,19);
        os.write("\\r\\n".getBytes()); // 换行

        os.flush(); // 立即刷新数据到文件中去,刷新后管道可以继续使用
        os.close(); // 关闭资源管道,关闭包含了刷新,关闭后管道不能使用了

三、字节流功能:实现文件的复制

字节是计算机中一切文件的组成,所以字节流适合做一切文件的复制。

复制是把源文件的全部字节一字不漏的转移到目标文件,只要文件前后的格式一样,绝对不会有问题。

需求:

原文件:D:\\xxx\\xxx.jpg
目标文件:D:\\xxx\\yyy.jpg

分析步骤:

(1) 创建一个字节输入流管道与源文件接通。
(2) 创建一个字节输出流与目标文件接通。
(3) 创建一个字节数组作为桶
(4) 从字节输入流管道中读取数据,写出到字节输出流管道即可。
(5) 关闭资源!

public class CopyDemo01 {
    public static void main(String[] args) {
        InputStream is = null ;
        OutputStream os = null ;
        try{
            /** (1)创建一个字节输入流管道与源文件接通。 */
            is = new FileInputStream("D:\\\\xxx\\\\xxx.jpg");
            /** (2)创建一个字节输出流与目标文件接通。*/
            os = new FileOutputStream("D:\\\\xxx\\\\yyy.jpg");
            /** (3)创建一个字节数组作为桶*/
            byte[] buffer = new byte[1024];
            /** (4)从字节输入流管道中读取数据,写出到字节输出流管道即可。*/
            int len = 0;
            while((len = is.read(buffer)) != -1){
                // 读取多少就倒出多少
                os.write(buffer, 0 , len);
            }
            System.out.println("复制完成!");
        }catch (Exception e){
            e.printStackTrace();
        } finally {
            /**(5)关闭资源! */
            try{
                if(os!=null)os.close();
                if(is!=null)is.close();
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
}

上述代码资源释放部分可以通过jdk1.7的 try-with-resources 模式来简化:

格式:

try(
       // 这里只能放置资源对象,用完会自动调用close()关闭
){
  	   // 这里放业务处理逻辑
}catch(Exception e){
     e.printStackTrace();
}
什么是资源?
     资源类一定是实现了Closeable接口,实现这个接口的类就是资源
     有close()方法,try-with-resources会自动调用它的close()关闭资源。

优化后的代码:

public class CopyDemo02 {
    public static void main(String[] args) {
        try(
                /** (1)创建一个字节输入流管道与源文件接通。 */
                InputStream is  = new FileInputStream("D:\\\\xxx\\\\xxx.jpg");
                /** (2)创建一个字节输出流与目标文件接通。*/
                OutputStream os = new FileOutputStream("D:\\\\xxx\\\\yyy.jpg");
                /** (5)关闭资源!是自动进行的 */
        ){
            /** (3)创建一个字节数组作为桶*/
            byte[] buffer = new byte[1024];
            /** (4)从字节输入流管道中读取数据,写出到字节输出流管道即可。*/
            int len = 0;
            while((len = is.read(buffer)) != -1){
                // 读取多少就倒出多少
                os.write(buffer, 0 , len);
            }
            System.out.println("复制完成!");
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

四、按序从文件中读字符

FileReader:文件字符输入流。
以内存为基准,把磁盘文件的数据以字符的形式读入到内存。简单来说,读取文本文件内容到内存中去。

构造器:

public FileReader(File file):创建一个字符输入流与源文件对象接通。
public FileReader(String filePath):创建一个字符输入流与源文件路径接通。

方法:

public int read():读取一个字符的编号返回! 读取完毕返回-1
public int read(char[] buffer):读取一个字符数组,读取多少个字符就返回多少个数量,读取完毕返回-1

小贴士:

字符流一个一个字符的读取文本内容输出,可以解决中文读取输出乱码的问题。字符流很适合操作文本文件内容。
但是:一个一个字符的读取文本内容性能较差!!

while循环一个一个字符读取
循环次数过多,性能太差

        Reader fr = new FileReader("xxx.txt");
        // while循环一个一个字符读取。
        // 定义一个变量存储一个字符的编号
        int ch ;
        while ((ch = fr.read()) != -1){
            System.out.print((char)ch);
        }

使用char[] ,字符数组实现性能较好的字符读取

        // 1.创建一个字符输入流管道与源文件接通
        Reader fr = new FileReader("xxx.txt");
          // a.按照字符数组读取数据使用循环
          char[] buffer = new char[1024]; // 1K
          // b.定义一个整数记录每次桶读取的字符数据量。
          int len;
          while((len = fr.read(buffer)) != -1 ) {
              // 读取多少倒出多少字符
              System.out.print(new String(buffer, 0 , len));
          }

五、按序向文件中写字符

FileWriter文件字符输出流。
以内存为基准,把内存中的数据按照字符的形式写出到磁盘文件中去。简单来说,就是把内存的数据以字符写出到文件中去。

构造器:

public FileWriter(File file):创建一个字符输出流管道通向目标文件对象。
public FileWriter(String filePath):创建一个字符输出流管道通向目标文件路径。
public FileWriter(File file,boolean append):创建一个追加数据的字符输出流管道通向目标文件对象。
public FileWriter(String filePath,boolean append):创建一个追加数据的字符输出流管道通向目标文件路径。

方法:

public void write(int c):写一个字符出去
public void write(String c)写一个字符串出去:
public void write(char[] buffer):写一个字符数组出去
public void write(String c ,int pos ,int len):写字符串的一部分出去
public void write(char[] buffer ,int pos ,int len):写字符数组的一部分出去

小贴士:

字符输出流可以写字符数据出去,总共有5个方法写字符。
覆盖管道:
Writer fw = new FileWriter(“xxx.txt”); // 覆盖数据管道
追加数据管道:
Writer fw = new FileWriter(“xxx.txt”,true); // 追加数据管道
换行:
fw.write("\\r\\n"); // 换行
读写字符文件数据建议使用字符流。

写一个字符出去:

// 1.创建一个字符输出流管道通向目标文件路径
//Writer fw = new FileWriter("xxx.txt"); // 覆盖数据管道
Writer fw = new FileWriter("xxx.txt",true); // 追加数据管道

// 2.写一个字符出去:public void write(int c):写一个字符出去
fw.write(97);   // 字符a
fw.write('b');  // 字符b
fw.write('澳'); // 字符澳,此时没有任何问题。
fw.write("\\r\\n"); // 换行
fw.close();

写一个字符串出去:

// 3.写一个字符串出去:public void write(String c)写一个字符串出去:
fw.write("Java是最优美的语言!");
fw.write("\\r\\n"); // 换行
fw.close();

写一个字符数组出去:

fw.write("我爱中国".toCharArray());
fw.write("\\r\\n"); // 换行
fw.close();

写字符串的一部分出去:

fw.write("Java是最优美的语言!",0,9);
fw.write("\\r\\n"); // 换行
fw.close();

写字符数组的一部分出去

fw.write("我爱中国".toCharArray(),0 ,2);
fw.write("\\r\\n"); // 换行
fw.close();

六、Buffered缓冲流

缓冲流可以提高字节流和字符流的读写数据的性能。

6.1 字节缓冲输入流:BufferedInputStream

字节缓冲输入流:

可以把低级的字节输入流包装成一个高级的缓冲字节输入流管道,从而提高字节输入流读数据的性能。

构造器:

public BufferedInputStream(InputStream in)

原理:

缓冲字节输入流管道自带了一个8KB的缓冲池,每次可以直接借用操作系统的功能最多提取8KB的数据到缓冲池中去,以后我们直接从缓冲池读取数据,所以性能较好!

// 1.定义一个低级的字节输入流与源文件接通
InputStream is = new FileInputStream("xxx.txt");

// 2.把低级的字节输入流包装成一个高级的缓冲字节输入流。
BufferedInputStream bis = new BufferedInputStream(is);

6.2 字节缓冲输出流:BufferedoutputStream

字节缓冲输出流:

可以把低级的字节输出流包装成一个高级的缓冲字节输出流,从而提高写数据的性能。

构造器:

public BufferedOutputStream(OutputStream os)

原理:

缓冲字节输出流自带了8KB缓冲池,数据就直接写入到缓冲池中去,性能极高了!

// 1.写一个原始的字节输出流
OutputStream os = new FileOutputStream("xxx.txt");
// 2.把低级的字节输出流包装成一个高级的缓冲字节输出流
BufferedOutputStream bos = new BufferedOutputStream(os);

6.3 字符缓冲输入流:BufferedReader

字符缓冲输入流:

可以把字符输入流包装成一个高级的缓冲字符输入流,可以提高字符输入流读数据的性能。

构造器:

public BufferedReader(Reader reader):

原理:

缓冲字符输入流默认会有一个8K的字符缓冲池,可以提高读字符的性能。

小贴士:

缓冲字符输入流除了提高了字符输入流的读数据性能,还多了一个按照行读取数据的功能(重点): public String readLine(): 读取一行数据返回,读取完毕返回null;

// 1.定义一个原始的字符输入流读取源文件
Reader fr = new FileReader("xxx.txt");
// 2.把低级的字符输入流管道包装成一个高级的缓冲字符输入流管道
BufferedReader br = new BufferedReader(fr);
// 定义一个字符串变量存储每行数据
String line;
// 使用一个循环读取数据(经典代码)
while((line = br.readLine())!=null){
    System.out.println(line);
}

6.4 字符缓冲输出流:BufferedWriter

字符缓冲输出流:

字符缓冲输出流可以把字符输入流包装成一个高级的缓冲字符输出流,可以提高字符输出流读数据的性能。

构造器:

public BufferedWriter(Writer writer):

原理:

缓冲字符输出流默认会有一个8K的字符缓冲池,可以提高读字符的性能。

小贴士:

字符缓冲输出流可以把字符输出流包装成一个高级的缓冲字符输出流,可以提高字符输出流读数据的性能。多了一个换行的功能:public void newLine():新建一行,效果等于"\\r\\n"。

// 1.定义一个低级的字符输出流写数据出去
Writer fw = new FileWriter("xxx.txt",true);

// 2.把低级的字符输出流包装成高级的缓冲字符输出流
BufferedWriter bw = new BufferedWriter(fw);

// 3.写字符输出
bw.write("IO流~~~~");
bw.newLine(); // 换行

bw.close();

七、缓冲流功能:实现文章顺序的恢复

需求:把《出师表》的文章顺序进行恢复到一个新文件中!!

三.侍中、侍郎郭攸之、费祎、董允等,此皆良实,志虑忠纯,是以先帝简拔以遗陛下。愚以为宫中之事,事无大小,悉以咨之,然后施行,必得裨补阙漏,有所广益。
八.愿陛下托臣以讨贼兴复之效,不效,则治臣之罪,以告先帝之灵。若无兴德之言,则责攸之、祎、允等之慢,以彰其咎;陛下亦宜自谋,以咨诹善道,察纳雅言,深追先帝遗诏,臣不胜受恩感激。
四.将军向宠,性行淑均,晓畅军事,试用之于昔日,先帝称之曰能,是以众议举宠为督。愚以为营中之事,悉以咨之,必能使行阵和睦,优劣得所。
二.宫中府中,俱为一体,陟罚臧否,不宜异同。若有作奸犯科及为忠善者,宜付有司论其刑赏,以昭陛下平明之理,不宜偏私,使内外异法也。
一.先帝创业未半而中道崩殂,今天下三分,益州疲弊,此诚危急存亡之秋也。然侍卫之臣不懈于内,忠志之士忘身于外者,盖追先帝之殊遇,欲报之于陛下也。诚宜开张圣听,以光先帝遗德,恢弘志士之气,不宜妄自菲薄,引喻失义,以塞忠谏之路也。
九.今当远离,临表涕零,不知所言。
六.臣本布衣,躬耕于南阳,苟全性命于乱世,不求闻达于诸侯。先帝不以臣卑鄙,猥自枉屈,三顾臣于草庐之中,咨臣以当世之事,由是感激,遂许先帝以驱驰。后值倾覆,受任于败军之际,奉命于危难之间,尔来二十有一年矣。
七.先帝知臣谨慎,故临崩寄臣以大事也。受命以来,夙夜忧叹,恐付托不效,以伤先帝之明,故五月渡泸,深入不毛。今南方已定,兵甲已足,当奖率三军,北定中原,庶竭驽钝,攘除奸凶,兴复汉室,还于旧都。此臣所以报先帝而忠陛下之职分也。至于斟酌损益,进尽忠言,则攸之、祎、允之任也。
五.亲贤臣,远小人,此先汉所以兴隆也;亲小人,远贤臣,此后汉所以倾颓也。先帝在时,每与臣论此事,未尝不叹息痛恨于桓、灵也。侍中、尚书、长史、参军,此悉贞良死节之臣,愿陛下亲之信之,则汉室之隆,可计日而待也。

分析:
    (1)创建一个缓冲字符输入流对象包装字符输入流接通源文件。
    (2)定义一个List集合用于存储每段文章。
    (3)定义一个循环按照行读取每段文章,存入到List集合中去。
    (4)对List集合中的每个元素按照首字符排序。
    (5)创建一个缓冲字符输出流管道通向目标文件。
    (6)遍历List集合中的每个元素,通过缓冲字符输出管道写出到目标文件。
    (7)释放资源
public static void main(String[] args)  {
    try(
            // (1)创建一个缓冲字符输入流对象包装字符输入流接通源文件。
            BufferedReader br =
                    new BufferedReader(new FileReader("xxx/xxx.txt"));
            // (5)创建一个缓冲字符输出流管道通向目标文件。
            BufferedWriter bw = new BufferedWriter(new FileWriter("xxx/yyy.txt"));
            ){

        // (2)定义一个List集合用于存储每段文章。
        List<String> datas = new ArrayList<>();
        // (3)定义一个循环按照行读取每段文章,存入到List集合中去。
        String line;
        while ((line = br.readLine()) != null){
            datas.add(line);
        }
        List<Character> sizes = new ArrayList<>();
        Collections.addAll(sizes,'零','一','二','三','四','五','六','七','八','九','十');
        // (4)对List集合中的每个元素按照首字符排序。
//          Collections.sort(datas, new Comparator<String>() {
//                @Override
//                public int compare(String s1, String s2) {
//                    // s1  三.侍中...
//                    // s2  八.愿陛....
//                    // indexOf获取元素在List集合中的索引。
//                    return sizes.indexOf(s1.charAt(0)) - sizes.indexOf(s2.charAt(0));
//                }
//          });
        Collections.sort(datas, ( s1,  s2) ->sizes.indexOf(s1.charAt(0)) - sizes.indexOf(s2.charAt(0)));
        System.out.println(datas);

        //  (6)遍历List集合中的每个元素,通过缓冲字符输出管道写出到目标文件。
        for (String data : datas) {
            bw.write(data);
            bw.newLine();
        }
    }catch (Exception e){
        e.printStackTrace();
    }
}

八、处理字符流不同编码读取乱码的问题

如果代码编码和读取的文件编码一致。字符流读取的时候不会乱码。
如果代码编码和读取的文件编码不一致。字符流读取的时候会乱码。
要提前注意编解码问题,或者通过调用转换流解决

九、字符输入转换流

InputStreamReader:

可以解决字符流读取不同编码乱码的问题。可以把原始的字节流按照当前默认的代码编码转换成字符输入流。也可以把原始的字节流按照指定编码转换成字符输入流

构造器:

public InputStreamReader(InputStream is):可以使用当前代码默认编码转换成字符流,几乎不用!
public InputStreamReader(InputStream is,String charset):可以指定编码把字节流转换成字符流

小贴士:

字符输入转换流可以解决不同编码读取乱码的问题!

public static void main(String[] args) throws Exception {
    // 代码:UTF-8    文件:GBK(ab我爱你: o o [oo] [oo] [oo])
    // 1.提取GBK文件的原始字节流
    InputStream is = new FileInputStream("xxx.txt");
    // 2.把原始字节输入流通过转换流,转换成 字符输入转换流InputStreamReader
    //Reader isr = new InputStreamReader(is); // 使用当前代码默认编码UTF-8转换成字符流,几乎不用!
    Reader isr = new InputStreamReader(is,"GBK"); // 指定编码把字节流转换成字符流
    // 3.包装成缓冲流
    BufferedReader br = new BufferedReader(isr);
    // 4.定义一个字符串变量存储每行数据
    String line;
    // 使用一个循环读取数据(经典代码)
    while((line = br.readLine())!=null){
        System.out.println(line);
    }
}

十、字符输出转换流

字符输出转换流:

OutputStreamWriter,可以指定编码把字节输出流转换成字符输出流,可以指定写出去的字符的编码。

构造器:

public OutputStreamWriter(OutputStream os) : 用当前默认编码UTF-8把字节输出流转换成字符输出流
public OutputStreamWriter(OutputStream os , String charset):指定编码把字节输出流转换成字符输出流

小贴士:

字符输出转换流可以指定编码把字节输出流转换成字符输出流。
从而实现指定写出去的字符编码!

public static void main(String[] args) throws Exception {
    // 1.写一个字节输出流通向文件
    OutputStream os = new FileOutputStream("xxx/xxx.txt");

    // 2.把字节输出流转换成字符输出流。
    // Writer fw = new OutputStreamWriter(os); // .把字节输出流按照默认编码UTF-8转换成字符输出流。
    Writer fw = new OutputStreamWriter(os,"GBK"); // .  把字节输出流按照指定编码GBK转换成字符输出流。
    fw.write("abc我是中国人");
    fw.close();
}

十一、序列化

11.1 对象字节输出流

对象序列化流(对象字节输出流):

ObjectOutputStream,把内存中的Java对象数据保存到文件中去。

构造器:

public ObjectOutputStream(OutputStream out)
序列化方法:public final void writeObject(Object obj)

注意:对象如果想参与序列化,对象必须实现序列化接口 implements Serializable ,否则序列化失败!

public class SerializeDemo01 {
    public static void main(String[] args) throws Exception {
        // 1.创建User用户对象
        User user = new User("tsgz","003197","铁扇公主");
        // 2.创建低级的字节输出流通向目标文件
        OutputStream os = new FileOutputStream("xxx/xxx.dat");
        // 3.把低级的字节输出流包装成高级的对象字节输出流ObjectOutputStream
        ObjectOutputStream oos = new ObjectOutputStream(os);
        // 4.通过对象字节输出流序列化对象:
        oos.writeObject(user);
        // 6.释放资源
        oos.close();
        System.out.println("序列化对象成功~~~~");
    }
}

11.2 对象字节输入流

对象反序列化(对象字节输入流):

ObjectInputStream,读取序列化的对象文件恢复到Java对象中。

构造器:

public ObjectInputStream(InputStream is)
序列化方法:public final Object readObject()

注意:

如果一个字段不想参数序列化:
transient修饰该成员变量,它将不参与序列化!

小贴士:

序列化版本号:
// 在实体类中加入序列版本号属性
private static final long serialVersionUID = 2L;
必须序列化使用的版本号和反序列化使用的版本号一致才可以正常反序列化!否则报错!

public static void main(String[] args) throws Exception {
    // 1.定义一个低级的字节输入流通向源文件
    InputStream is = new FileInputStream("xxx/xxx.dat");
    // 2.把字节输入流包装成高的对象字节输入流
    ObjectInputStream ois = new ObjectInputStream(is);
    // 3.反序列化
    User user = (User) ois.readObject();
    System.out.println(user);
    System.out.println("反序列化完成!");
}

十二、打印流

打印流:PrintStream / PrintWriter.

打印流的作用:
    1.可以方便,快速的写数据出去。
    2.可以实现打印啥出去,就是啥出去。
打印流的构造器:
    public PrintStream(OutputStream os):
    public PrintStream(String filepath):

小结:
     打印流可以方便,且高效的打印各种数据。
     PrintStream不光可以打印数据,还可以写"字节数据"出去。
     PrintWriter不光可以打印数据,还可以写"字符数据"出去。
public class PrintStreamDemo01 {
    public static void main(String[] args) throws Exception {
        // 1.打印流PrintStream
        //OutputStream os = new FileOutputStream("xxx/xxx.txt");
        //PrintStream ps = new PrintStream(os);
        PrintStream ps = new  PrintStream("xxx/yyy.txt");
        //PrintWriter pw = new  PrintWriter("xxx/yyy.txt");

        ps.println(97); // 写97
        ps.println(110); // 写110
        ps.println(99.8);
        ps.println(false);
        ps.println('徐');

        // 写字节数据出去
        // ps.write("我爱你".getBytes());

        ps.close();
    }
}

打印流改变输出的流向。重定向。

public class PrintStreamDemo02 {
    public static void main(String[] args) throws Exception {
        System.out.println("==0==");
        PrintStream ps = new PrintStream("xxx/xxx.txt");
        System.setOut(ps); // 让系统的输出流向打印流。

        System.out.println("==1==");
        System.out.println("==2==");
        System.out.println("==3==");
        System.out.println("==4==");
        System.out.println("==5==");
    }
}

以上是关于如何高效的使用IO流?字节流字符流缓冲流序列化对象流打印流全整理的主要内容,如果未能解决你的问题,请参考以下文章

Java IO流 - 缓冲流的详细使用介绍

Java IO流 - 缓冲流的详细使用介绍

JavaSE基础九----<IO流 >流的体系和分类,字节流,字节缓冲流

从零开始的Java开发1-6-4 Java输入输出流:File类绝对路径和相对路径字节流缓冲流字符流对象序列化

IO流——字节流

IO流相关知识(File,字节流,字符流,特殊操作流(标准输入流,标准输出流,对象序列化与反序列化,properties与IO流结合))相关知识总结