Java高级编程—I/O流(包括字节输入流、字节输出流、字符输出流、字符输入流、缓冲流、序列化流、反序列化流等,详解 附有代码+案例)

二十七.I/O流

(遇见异常直接抛,默认采用alt+enter提示的第一种方式处理异常)

27.1概述

什么是I/O流:存储和读取数据的解决方案

作用:用于读写数据
(图片来自B站Java视频)
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

27.2 分类

按照流向区分:

  • 输入流 :把数据从其他设备上读取到内存中的流。
  • 输出流 :把数据从内存 中写出到其他设备上的流。

在这里插入图片描述

按照操作文件的类型分:

  • 字节流:操作所有类型的文件,以字节为单位,读写数据的流。
  • 字符流:只能操作纯文本文件,以字符为单位,读写数据的流。

用windows系统自带的记事本打开且能读懂的文件为纯本文文件,包括txt文件,md文件,xml文件,lrc文件,等等…

在这里插入图片描述

27.3 字节输出流

FileOutStream:字节输出流

27.3.1 数据写入本地文件

FileOutStream:可以把程序中的数据写到本地文件上,是字节流的基本流。

  • 创建字节输出流对象

    细节1:参数是字符串表示的路径或者是File对象都是可以的
    细节2:如果文件不存在会创建一个新的文件,但是要保证父级路径是存在的。
    细节3:如果文件已经存在,则会清空文件.
          (如果文件已经存在内容,则会清空文件原有内容,然后写入的新内容)
    
  • 写数据

    write方法的参数是整数,但是实际上写到本地文件中的是整数在ASCII上对应的字符

  • 释放资源

    每次使用完流之后都要释放资源,解除占用

方法名说明
void write(int b)一次写一个字节数据
void write(byte[] b)一次写一个字节数组数据
void write(byte[] b, int off, int len)一次写一个字节数组的部分数
import java.io.FileOutputStream;
import java.io.IOException;

public class Test01 {
 public static void main(String[] args) throws IOException {
   
FileOutputStream fos = new FileOutputStream("code_java02\\kwh.txt");
   
       byte[] bytes = {97,98,99};
   
        fos.write(97);// a
        fos.write(bytes);// a b c 
        fos.write(bytes,0,2);// a b
        fos.close();
    }
}

27.3.2 换行、续写

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

public class Test02 {
    public static void main(String[] args) throws IOException {

        //默认false:关闭续写,会清空文件
        // true:打开续写开关,不会清空文件
        FileOutputStream fos = new FileOutputStream("code_java02\\kwh.txt",true);

        String str = "nihao";
        // 将字符串编程字节数组
        byte[] bytes1 = str.getBytes();
        fos.write(bytes1);

        // 换行
        String str2 = "\r\n";
        byte[] bytes2 = str2.getBytes();
        fos.write(bytes2);
      
        String str3 = "tianqihenhao";
        byte[] bytes3 = str3.getBytes();
        fos.write(bytes3,0,bytes3.length);

        fos.close();
    }
}

27.4字节输入流

FileInputStream:字节输入流

27.4.1 读取数据到程序

操作本地的字节输入流,把本地文件的数据读取到程序中。

  • 创建字节输入流对象

    如果文件不存在,就直接报错。

  • 读数据

    一次读一个字节,读出来的是数据在ASCII上对应的数字

    读到文件末尾处没有数据,read方法返回-1

  • 释放资源

import java.io.FileInputStream;
import java.io.IOException;

public class Test03 {
 public static void main(String[] args) throws IOException {

        // 创建字节输入流对象;    kwh.txt里有abc
        FileInputStream fis = new FileInputStream("code_java02\\kwh.txt");
        // 读数据
        int read = fis.read();
        System.out.println(read);//97

        fis.close();
    }
}

27.4.2 循环读取

一次循环读取一个字节

import java.io.FileInputStream;
import java.io.IOException;

public class Test04 {
    public static void main(String[] args) throws IOException {

        // 创建对象  kwh.txt里有abc
        FileInputStream fls = new FileInputStream("code_java02\\kwh.txt");

        // 定义变量,记录读取的数据
        int b ;
      
         // b =fls.read();
        // System.out.println(b);//97
      
        // 循环读取
        //read :表示读取数据,而且是读取一个数据就移动一次指针
        while ((b =fls.read()) != -1){
            System.out.print((char) b);
        }
        // 释放资源
        fls.close();
    }
}

27.4.3 拷贝数据

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class Test05 {
 public static void main(String[] args) throws IOException {

        FileInputStream fis = new FileInputStream("E:\\software\\ideak\\ideapro\\kwhcode\\code_java02\\kkk.txt");
   
        FileOutputStream fos = new FileOutputStream("code_java02\\www.txt");
        // 定义变量,记录读取的数据
        int b;

        // 边读边写
       //一次读写一个字节
        while ((b= fis.read()) != -1){
            fos.write(b);
        }

        // 释放资源
        fis.close();
        fos.close();

    }
}

27.4.4 一次读取多个

方法说明
public in read()一次读取一个字节
public int read(byte[] buffer)一次读一个字节数组数据
import java.io.FileInputStream;
import java.io.IOException;

public class Test06 {
 public static void main(String[] args) throws IOException {

        // kwh.txtl里有abc
        FileInputStream fis = new FileInputStream("code_java02\\kwh.txt");

        // 定义一个长度为2的字符数组,表示每次读取2个字节
        //将读到的数据再返回到数组bytes中
        byte[] bytes = new byte[2];
        //一次读取多个字节数据,具体读多少,跟数组的长度有关
        //返回值:本次读取到了多少个字节数据
        int len1 = fis.read(bytes);
        System.out.println(len1);//2
        //将bytes数组从0索引开始,一共把len1个字节变成字符串
        String str1 = new String(bytes,0,len1);
        System.out.println(str1);//ab

        int len2 = fis.read(bytes);
        System.out.println(len2);// 1

        String str2 = new String(bytes,0,len2);
        System.out.println(str2);//c

        // int len3 = fis.read(bytes);
        // System.out.println(len3);//-1
        // String str3 = new String(bytes);
        // System.out.println(str3);//cb

        fis.close();

    }
}
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class Test07 {
 public static void main(String[] args) throws IOException {


        FileInputStream fis = new FileInputStream("E:\\software\\ideak\\ideapro\\kwhcode\\code_java02\\hhh.txt");
   
        FileOutputStream fos = new FileOutputStream("code_java02\\hhh02.txt");

        byte[] bytes = new byte[1024 * 1024 * 5];
        // 定义要读取的数据的长度,即字节数
        int len;
        while ((len = fis.read(bytes)) != -1){
            // 都多少写多少
            fos.write(bytes,0 ,len);
        }
				//释放资源
        fos.close();
        fis.close();

    }
}

27.6 字符输入流

FileReader:字符输入流

使用场景:对纯文本文件进行读写操作。

字符流的底层就是字节流

字符流 = 字节流+字符集

特点:

  • 输入流:一次读一个字节,遇到中文时,一次读多个字节。
  • 输出流:底层会把数据按照指定的编码方式进行编码,变成字节再写到文件中。

27.6.1 FileReader的使用

  • 创建字符输入流对象

    构造方法说明
    public FileReader(File file)创建字符输入流关联本地文件
    public FileReader(String Path)创建字符输入流关联本地文件

    如果文件不存在,就直接报错。

  • 读取数据

    成员方法说明
    public int read()读取数据,读到末尾返回-1
    public int read(char[] buffer)读取多个数据,读到末尾返回-1

    细节1: 按照字节进行读取,遇到中文,一次读多个字节。读取后解 码。返回一个整数。

    细节2: 读到文件末尾,read方法返回-1

  • 释放资源

import java.io.FileReader;
import java.io.IOException;

public class Test09 {
    public static void main(String[] args) throws IOException {

        // 创建字符输入流对象
      FileReader fr = new FileReader("code_java02\\a.txt");

        // 定义读取的字节数
      //  // 记录读取的汉字解码后的十进制数
        int ch;

        //2.读取数据 read()
        //字符流的底层也是字节流,默认也是一个字节一个字节的读取的。
        //如果遇到中文就会一次读取多个,GBK一次读两个字节,UTF-8一次读三个字节

        //read()细节:
        //1.read():默认也是一个字节一个字节的读取的,如果遇到中文就会一次读取多个
        //2.在读取之后,方法的底层还会进行解码并转成十进制。
        //  最终把这个十进制作为返回值
        //  这个十进制的数据也表示在字符集上的数字
        //  英文:文件里面二进制数据 0110 0001
        //          read方法进行读取,解码并转成十进制97
        //  中文:文件里面的二进制数据 11100110 10110001 10001001
        //          read方法进行读取,解码并转成十进制27721

        // 想看到中文汉字,就是把这些十进制数据,再进行强转就可以了

        // 循环读取
        while ((ch = fr.read()) != -1){
            // System.out.println(ch);十进制数
          //把解码出的十进制数强转成对应的字符
            System.out.print((char) ch);
        }
        // 释放资源
        fr.close();

    }
}
import java.io.FileReader;
import java.io.IOException;

public class Test10 {
 public static void main(String[] args) throws IOException {

         FileReader fr = new FileReader("code_java02\\a.txt");
        // 记录读取的个数
        int len;

        // 一次读取两个,并把数据返回到chars数组里
        char[] chars = new char[2];

       //read(chars):读取数据,解码,强转三步合并了,把强转之后的字符放到数组当中
        //相当于空参的read + 强转类型转换
        while ((len = fr.read(chars)) != -1){
           // System.out.println(len);//2
            // 将读取的数据放到chars数组后变成字符串输出
            System.out.print(new String(chars));
        }

        fr.close();
    }
}

27.7 字符输出流

FileWriter:字节输出流

构造方法说明
public FileWriter(File file)创建字符输出流关联本地文件
public FileWriter(String pathname)创建字符输出流关联本地文件
public FileWriter(File file, boolean append)创建字符输出流关联本地文件,续写
public FileWriter(String pathname, boolean append)创建字符输出流关联本地文件,续写
成员方法说明
void write(int c)写出一个字符
void write(String str)写出一个字符串
void write(String str, int off, int len)写出一个字符串的一部分
void write(char[] cbuf)写出一个字符数组
void write(char[] cbuf, int off, int len)写出字符数组的一部分
import java.io.FileWriter;
import java.io.IOException;

public class Test11 {
 public static void main(String[] args) throws IOException {

 FileWriter fw = new FileWriter("code_java02\\a.txt",true);

   			//根据字符集进行编码,编码成三个字节写入文件
        fw.write(25105);
        fw.write("你好");

        char[] chars = {'今','天','好'};
        fw.write(chars);
        fw.write(chars,0,1);
        fw.write(chars,1,2);

        String str = "苹果葡萄";
        fw.write(str,0,2);
        
        fw.close();

    }
}

27.8. 缓冲流

高级流

在这里插入图片描述

27.8.1 字节缓冲流

原理:底层自带了长度为8192的缓冲区提高性能。

方法名称说明
public BufferedInputStream(InputStream is)把基本流包装成高级流,提高数去数据性能
public BufferedOutputStream(OutputStream os)把基本流包装成高级流,提高数去数据性能
字节缓冲输入流的构造方法:
public BufferedInputStream(InputStream is)

字节缓冲输出流的构造方法:
public BufferedOutputStream(OutputStream os)
27.8.1.1拷贝文件(一)

一次读写一个字节

import java.io.*;

public class Test01 {

 public static void main(String[] args) throws IOException {
      //利用字节缓冲流拷贝文件
      //将a.txt里的内容写到aa.txt,aa.txt不存在

      BufferedInputStream bis = new BufferedInputStream(new FileInputStream("code_java02\\filedemo\\a.txt"));

      BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("code_java02\\filedemo\\aa.txt"));

      // 记录读取的数据,一次读写一个字节
      int b;
      // 循环读取,读取的是缓冲区中数据,一次性读取8192个字节数据
      while ((b= bis.read()) != -1){
         // 将读取的数据再写入目的地
         bos.write(b);
      }

      // 关闭流
      bos.close();
      bis.close();

   }
}
27.8.1.2 拷贝文件(二)

一次读写多个字节

package bufferedstreamdemo;

import java.io.*;

public class Test02 {
    public static void main(String[] args) throws IOException {

        // 创建缓冲流对象
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("code_java02\\filedemo\\a.txt"));

        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("code_java02\\filedemo\\a2.txt"));


        // 定义数组,将读取的数据存入字节数组
        //一次读取多个字节
        byte[] bytes = new byte[1024];
        //记录读取的数据(字节)
        int len;
        // 循环将读取的字节数据写入字节数组
        while ((len = bis.read(bytes)) != -1){
            // 写入目的文件,一次写一个字节数组
            bos.write(bytes,0,len);
        }

        // 关闭流
        bos.close();
        bis.close();
    }
}

27.8.2字符缓冲流

构造方法

方法名称说明
public BufferedReader(Reader r)把基本流变成高级流
public BufferedWriter(Writer r)把基本流变成高级流
27.8.2.1字符缓冲输入流
构造方法:
         public BufferedReader(Reader r)
特有方法:
         public String readLine()   读一整行
package bufferedstreamdemo;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class Test03 {
 public static void main(String[] args) throws IOException {
      
        // 创建字符缓冲输入流对象
        BufferedReader br = new BufferedReader(
                             new FileReader("code_java02\\filedemo\\a.txt"));

        String line;

        while ((line = br.readLine()) != null){
            System.out.println(line);
        }
        // 释放资源
        br.close();

    }
}
27.8.2.2 字符缓冲输出流
构造方法:
         public BufferedWriter(Writer r)
特有方法:
        public void newLine()      跨平台的换行
package bufferedstreamdemo;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;

public class Test04 {
 public static void main(String[] args) throws IOException {
        // 创建字符输出流对象
        //a3.txt 不存在则会直接创建
       FileWriter fw = new FileWriter("code_java02\\filedemo\\a3.txt",true);

        BufferedWriter bw = new BufferedWriter(fw);

        // 写入内容
        bw.write("数风流人物,还看今朝。");
        // 换行
        bw.newLine();
        bw.write("俱往矣");

        // 释放资源
        bw.close();
    }
}

27.8.3 Test

27.9 转换流

高级流

字符转换输入流:InputStreamReader

字符转换输出流:OutputStreamWriter

27.9.1概述

是字符流和字节流之间的桥梁。

在这里插入图片描述

将字节流转换成字符流就可以拥有字符流的特性,同时字节流可以使用字符流中的方法。

字符流特性,比如:

  • 不会乱码
  • 根据字符集一次读取多个数据

示意图:

在这里插入图片描述

27.9.2Test

27.9.2.1test01

利用转换流按照指定字符编码读取

package convertstream;

import java.io.*;

public class Test01 {
 public static void main(String[] args) throws IOException {

        FileInputStream fis  = new FileInputStream( "code_java02\\filedemo\\gbkfile.txt");
        // 创建转换流对象
       InputStreamReader isr = new InputStreamReader(fis,"GBK");

        int b;
        while ((b = isr.read()) != -1){
            System.out.print((char) b);
        }
        isr.close();
    }
}
27.9.2.2 test02

利用转换流按照指定字符编码写出

package convertstream;

import java.io.*;

public class Test03 {
 public static void main(String[] args) throws IOException {

        // gbkfile02.txt 不存在则创建
        FileOutputStream fos  = new FileOutputStream("code_java02\\filedemo\\gbkfile02.txt",true);
       // 创建转换流对象
       OutputStreamWriter osw = new OutputStreamWriter(fos,"GBK");

        osw.write("吃了么");

        osw.close();
    }
}
27.9.2.3 test03

将本地文件中的GBK文件,转成UTF-8

package convertstream;

import java.io.*;

public class Test04 {
 public static void main(String[] args) throws IOException {
      
        // gbkfile03.txt 不存在 则创建

        // 创建转换流读出
        FileInputStream fis = new FileInputStream("code_java02\\filedemo\\gbkfile.txt");
        InputStreamReader isr = new InputStreamReader(fis,"GBK");

        // 创建转换流写入
        FileOutputStream fos = new FileOutputStream("code_java02\\filedemo\\gbkfile03.txt");
        OutputStreamWriter osw = new OutputStreamWriter(fos,"UTF-8");

   		  //一次读写一个字节
        // int b;
        // while ((b=isr.read()) != -1){
        //     osw.write(b);
        // }
   
       //一次读写多个字节
        char[] chars = new char[2];
        int b;
        while ((b = isr.read(chars)) != -1){
            osw.write(chars);
        }

        osw.close();
        isr.close();
    }
}
27.9.2.4 test04

利用字节流读取文件中的数据,每次读一整行,而且不能出现乱码

package convertstream;

import java.io.*;

public class Test05 {
    public static void main(String[] args) throws IOException {
        /*
        利用字节流读取文件中的数据,每次读一整行,而且不能出现乱码
          1.字节流在读取中文的时候,是会出现乱码的,但是字符流可以搞定
          2.字节流里面是没有读一整行的方法的,只有字符缓冲流才能搞定
         */

        // 创建字节流对象
       FileInputStream fis = new FileInputStream("code_java02\\filedemo\\a.txt");

        // 将字节流转换成字符流
        InputStreamReader isr = new InputStreamReader(fis);

        // 将字符流包装成字符缓冲流
        BufferedReader br = new BufferedReader(isr);

        String line;
        while ((line = br.readLine()) != null){
            System.out.println(line);
        }

        // 释放资源
        br.close();
    }
}

27.10 序列化流

在这里插入图片描述

也叫 对象操作输出流

可以把Java中的对象写到本地文件中

高级流,也是用来包装基本流的

构造方法:
     public ObjectOutputStream(OutputStream out) 
     把基本流变成高级流

成员方法:
       public final void writeObject(Object obj)                    把对象序列化(写出)到文件中去
//Student的标准JavaBean类
// Student实现Serializable接口
//Serializable接口里面是没有抽象方法,标记型接口一旦实现了这个接口,那  么就表示当前的Student类可以被序列化
//属性:学生姓名,学生年龄
=================================================
  //测试类
package objectstream.test01;

import java.io.*;

public class StudentTest {
 public static void main(String[] args) throws IOException {

        // 创建学生对象
        Student stu1 = new Student("小明",18);

// 创建序列化流的对象
      ObjectOutputStream oos =  new ObjectOutputStream(new FileOutputStream("code_java02\\filedemo\\objfile.txt"));

        // 写出数据
        oos.writeObject(stu1);

        // 释放资源
        oos.close();
    }
}

27.11 反序列化流

也叫对象操作输入流,把序列化到本地文件中的对象读取到程序中。

构造方法:
      public ObjectInputStream(InputStream out) 
      把基本流变成高级流
成员方法:
     public Object readObject()              
     把序列化到本地文件中的对象,读取到程序中来
//同27.10中的JavaBean类
=================================================
package objectstream.test01;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;

public class StudentTest02 {
   public static void main(String[] args) throws IOException, ClassNotFoundException {

       // 创建反序列流对象
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("code_java02\\filedemo\\objfile.txt"));

        // 读出数据
        // Object o = ois.readObject();
     
        //想看到真正的对象需要强转
        Student stu   = (Student) ois.readObject();
        // 打印对象
        System.out.println(o);
        // 释放资源
        ois.close();

    }
}

化到本地文件中的对象读取到程序中。

构造方法:
      public ObjectInputStream(InputStream out) 
      把基本流变成高级流
成员方法:
     public Object readObject()              
     把序列化到本地文件中的对象,读取到程序中来
//同27.10中的JavaBean类
=================================================
package objectstream.test01;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;

public class StudentTest02 {
   public static void main(String[] args) throws IOException, ClassNotFoundException {

         // 创建反序列流对象
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("code_java02\\filedemo\\objfile.txt"));

        // 读出数据
        // Object o = ois.readObject();
     
        //想看到真正的对象需要强转
        Student stu   = (Student) ois.readObject();
        // 打印对象
        System.out.println(o);
        // 释放资源
        ois.close();

    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

蔚一

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值