IO系列之字节流和字符流

IO流的分类

  • 根据处理数据类型的不同分为:字符流和字节流

  • 根据数据流向不同分为:输入流和输出流

进行输入、输出操作一般都会按照如下步骤进行:

  • 通过File类定义一个要操作文件的路径
  • 通过字节流或字符流的子类对象为父类对象实例化
  • 进行数据的读(输入)、写(输出)操作
  • 数据流属于资源操作,资源操作必须关闭

java.io包定义了两类流:

  • 字节流(JDK 1.0):InputStream、OutputStream
  • 字符流(JDK 1.1):Writer、Reader
1. 字节流
1.1 字节输出流(OutputStream)

OutputStream这个抽象类是表示字节输出流的所有类的超类。

输出流接收输出字节并将其发送到某个接收器。

需要定义OutputStream子类的应用OutputStream必须至少提供一个写入一个字节输出的方法。

OutputStream类提供了三个输出的方法:

  • 输出单个字节:public abstract void write(int b)
  • 输出全部字节数组:public void write(byte[] b)
  • 输出部分字节数组:public void write(byte[] b,int off,int len)

OutputStream本身属于抽象类,如果想为抽象类进行对象的实例化操作,需要使用抽象类的子类,进行文件操作可以使用FileOutputStream子类。在这个子类中定义了如下构造方法:

  • FileOutputStream(File file) 创建文件输出流以写入由指定的File对象表示的文件
  • FileOutputStream(File file, boolean append) 文件内容追加

使用全部字节数组进行输出示例:

     //1. 定义要输出的文件路径
        File file = new File("E:"+File.separator+"demo"+File.separator+"test.txt");
        //如果目录不存在则先创建目录
        if(file.getParentFile().exists()){
            file.getParentFile().mkdirs();
        }

        //2. 应该使用OutputStream和其子类进行对象的实例化,此时目录存在,文件还不存在
        OutputStream outputStream = new FileOutputStream(file);

        //3. 进行文件内容的输出
        String str = "好好学习,天天向上";
        //将字符串转为byte数组
        byte[] data = str.getBytes();

        outputStream.write(data);

        //4. 关闭资源
        outputStream.close();

使用部分字节数组输出示例

 //1. 定义要输出的文件路径
        File file = new File("E:"+File.separator+"demo"+File.separator+"study.txt");
        //如果目录不存在则先创建目录
        if(file.getParentFile().exists()){
            file.getParentFile().mkdirs();
        }

        //2. 应该使用OutputStream和其子类进行对象的实例化,此时目录存在,文件还不存在
        OutputStream outputStream = new FileOutputStream(file);

        //3. 进行文件内容的输出
        String str = "我们要好好学习技术,然后找个好工作,多赚点钱,补贴家用,实现自我价值,成为一个对社会有用的人";
        //将字符串转为byte数组
        byte[] data = str.getBytes();

        outputStream.write(data,0,6);

        //4. 关闭资源
        outputStream.close();
1.2 字节输入流:InputStream

InputStream抽象类是表示输入字节流的所有类的超类。

需要定义InputStream子类的应用InputStream必须始终提供一种返回输入的下一个字节的方法。

InputSream提供了三个输入的方法

  • public abstract int read() 从输入流读取数据的下一个字节
  • public int read(byte[] b) 从输入流读取一些字节数,并将它们存储到缓冲区b 。 实际读取的字节数作为整数返回。 该方法阻塞直到输入数据可用,检测到文件结束或抛出异常。
  • public int read(byte[] b,int off,int len) 从输入流读取len字节的数据到一个字节数组。 尝试读取多达len个字节,但可以读取较小的数字。 实际读取的字节数作为整数返回。该方法阻塞直到输入数据可用,检测到文件结束或抛出异常。

使用FileInputStream读入文件示例

  //1. 定义要输入的文件路径
 File file = new File("E:"+File.separator+"demo"+File.separator+"study.txt");
//判断文件是否存在后才可以进行读取
if(file.exists()){
    // 2. 使用FileInputStream进行读取
    InputStream inputStream = new FileInputStream(file);
    //准备处理一个1024的数组
    byte[] data = new byte[1024];
    //字节数组的操作脚标
    int foot = 0;
    //表示每次读取的字节数据
     int temp = 0;
    //读取一个字节
    while((temp = inputStream.read()) != -1){
         if(temp != -1){
          data[foot++] = (byte)temp;
         }
    }
    //4. 关闭流
    inputStream.close();
    System.out.println("["+new String(data,0,foot)+"]");
    }
}
2. 字符流
2.1 字符输出流:Writer

Writer是用于写入字符流的抽象类。子类必须实现的唯一方法是write(char [],int,int),flush()和close()。 然而,大多数子类将覆盖这里定义的一些方法,以便提供更高的效率,或者附加功能。

Writer提供的常用方法

  • write(char[] cbuf) 写入一个字符数组。
  • write(char[] cbuf, int off, int len) 写入字符数组的一部分。
  • write(int c) 写一个字符
  • write(String str) 写一个字符串
  • write(String str, int off, int len) 写一个字符串的一部分。
  • append(char c) 附加指定的字符
  • close() 关闭流,先刷新。
  • flush() 刷新流。

使用字符输出流输出字符串示例

 //1. 定义要输出的文件路径
 File file = new File("E:"+File.separator+"demo"+File.separator+"writer.txt");
//如果目录不存在则创建
if(!file.getParentFile().exists()){
    file.getParentFile().mkdirs();
}

//2. 实例化Writer类对象
Writer out = new FileWriter(file);

//3. 进行内容输出
String str = "好好学习,天天向上!!!";
//输出字符串数据
out.write(str);

//4. 关闭流
out.close();
2.2 字符输入流:Reader

用于读取字符流的抽象类。 子类必须实现的唯一方法是read(char [],int,int)和close()。 然而,大多数子类将覆盖这里定义的一些方法,以便提供更高的效率以及附加的功能。

Reader提供的常用方法

  • read() 读一个字符
  • read(char[] cbuf) 将字符读入数组。
  • read(char[] cbuf, int off, int len) 将字符读入数组的一部分。
  • read(CharBuffer target) 尝试将字符读入指定的字符缓冲区。
  • ready() 告诉这个流是否准备好被读取。
  • close() 关闭流并释放与之相关联的任何系统资源。
  • mark(int readAheadLimit) 标记流中的当前位置。
  • reset() 重置流。

读入文件可以使用子类FileReader,示例代码如下:

 //1. 定义要输入的文件路径
File file = new File("E:"+File.separator+"demo"+File.separator+"writer.txt");
//判断文件是否存在后才可以进行读取
if(file.exists()){
            
    // 2. 为Reader类对象实例化
    Reader input = new FileReader(file);
            
    // 3. 进行数据读取
    char[] c = new char[1024];
    int len = input.read(c);
            
    //4. 关闭流
    input.close();
    
    System.out.println(new String(c,0,len));
}

与字节输入流相比结构几乎一样,只是数据类型由byte变为char

3. 字节流与字符流的区别
  • 字节流直接与终端进行数据交互,字符流需要将数据经过缓存区处理后才可以输出
  • 读写单位不同:字节流以字节(8bit)为单位,字符流以字符为单位,根据码表映射字符,一次可能读多个字节。
  • 字节流处理二进制数据,字符流处理文本文件
  • 字节流可以转为字符流,而字符流不能转为字节流
  • 进行中文处理时优先考虑字符流
4. 字节流转换为字符流

在java.io包里面提供了两个类:InputStreamReader和OutputStreamWriter用于将字节流转为字符流

名称:InputStreamReaderOutputStreamWriter
定义结构:public class InputStreamReader extends ReaderInputStreamReader(InputStream in)
构造方法:public class OutputStreamWriter extends WriterOutputStreamWriter(OutputStream out)

InputStreamReader是将字节输入流转为字符输入流:它读取字节,并使用指定的charset将其解码为字符。 它使用的字符集可以由名称指定,也可以被明确指定,或者可以接受平台的默认字符集。每个调用InputStreamReader的read()方法会导致从底层字节输入流读取一个或多个字节。 为了使字节有效地转换为字符,可以从底层流读取比满足当前读取操作所需的更多字节。

为了最大的效率,请考虑在BufferedReader中包装一个InputStreamReader。 例如:BufferedReader in = new BufferedReader(new InputStreamReader(System.in));

OutputStreamWriter是将字节输出流转为字符输出流。 它使用的字符集可以由名称指定,也可以被明确指定,或者可以接受平台的默认字符集。
每次调用write()方法都会使编码转换器在给定字符上被调用。 所得到的字节在写入底层输出流之前累积在缓冲区中。 可以指定此缓冲区的大小。 请注意,传递给write()方法的字符不会缓冲。

为了最大的效率,请考虑在BufferedWriter中包装一个OutputStreamWriter,以避免频繁的转换器调用。 例如:Writer out = new BufferedWriter(new OutputStreamWriter(System.out));

将字节输出流转为字符输出流示例

 File file = new File("E:"+ File.separator+"demo"+File.separator+"study.txt");
 if(!file.getParentFile().exists()){
    file.getParentFile().mkdirs();
        }
    //字节流
    OutputStream output = new FileOutputStream(file);

    //将字节流转换为字符流
    Writer out = new OutputStreamWriter(output);
    String c = "Hello World!";
    //进行输出
    out.write(c);

    out.flush();
    out.close();

将字节输入流转为字符输入流示例

 File file = new File("E:"+ File.separator+"demo"+File.separator+"study.txt");
 if(!file.getParentFile().exists()){
    file.getParentFile().mkdirs();
        }

    //字节输入流
    InputStream in = new FileInputStream(file);

    //将字节输入流转为字符输入流
    Reader input = new InputStreamReader(in);
    char[] c = new char[1024];
    //读数据
    input.read(c);

    //关闭流
    input.close();

    System.out.println(new String(c));
  • 两个转换类都是字符流的子类,属于字符流与字节流沟通的桥梁
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值