博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
字符输入流Reader简要概括
阅读量:6927 次
发布时间:2019-06-27

本文共 6355 字,大约阅读时间需要 21 分钟。

字符输入流Reader组成结构

本篇将对JAVA I/O流中的字符输入流Reader做个简单的概括:

总得来说,每个字符输入流类都有一个对应的用途,如下:

  • 字符流基类:Reader
  • 字节流转字符流:InputStreamReader                //读取字节输入流中的字符
  • 字符文件读取相关:FileReader                          //读取文件中的字符
  • 字符数组转字符流:CharArrayReader                //读取字符数组中的字符
  • 线程内部通信(管道):PipedReader                    //读取管道中的字符
  • 字符串转字符流:StringReader                        //读取字符串中的字符
  • 缓冲流:BufferedReader                                //可装饰其它字符输入流,增加缓冲功能
  • 过滤流:FilterReader                                     //可装饰其它字符输入流,增加过滤功能
  • Parse Input:PushbackReader(可以回退读取)、LineNumberReader(显示行号)   //可装饰其它字符输入流,增加回退读取和显示行号功能

再看下Reader的组成结构(下图);

下面将对各个字符输入流做个详细介绍;

InputStreamReader

InputStreamReader继承字符流抽象类Reader,每个构造方法都包含一个字节流InputStream入参,功能显而易见,就是通过字节流InputStream得到字符流

PS:无论是构造方法里对字节流的处理(StreamDecoder.forInputStreamReader),还是字符流的读取(StreamDecoder.read),底层都是通过StreamDecoder类实现的,有兴趣的可以深入了解~

 举个例子,如下,为方便阅读,不做异常处理:

package io;import java.io.IOException;import java.io.InputStreamReader;import java.io.Reader;public class IOTest {    public static void main(String[] args) throws IOException  {        //通过“标准”字节输入流得到一个字符输入流        Reader reader = new InputStreamReader(System.in);        //读取一个字符并打印        System.out.println((char)reader.read());        //关闭流        reader.close();    }}//输出示例//键盘输入0//显示0

FileReader

FileReader继承字符流InputStreamReader,通过本地字符文件得到字符流,查看其构造方法,都是先根据传入的参数生成一个FileInputStream字节流对象,然后调用父类InputStreamReader的构造方法得到字符流;

举个简单的例子:

package io;import java.io.FileReader;import java.io.IOException;import java.io.Reader;public class IOTest {    public static void main(String[] args) throws IOException  {        //读取本地文件,得到字符流        Reader reader = new FileReader("C:\\test.txt");        //读取一个字符并打印        System.out.println((char)reader.read());        //关闭流        reader.close();    }}

CharArrayReader

CharArrayReader可以让我们通过字符数组得到字符流,构造方法如下

查看源码,可以发现在CharArrayReader里面直接使用外部字符数组的引用,也就是说,即使得到字符流对象后,当改变外部数组时,通过流读取的字符也会改变,如下代码实例:

package io;import java.io.CharArrayReader;import java.io.IOException;import java.io.Reader;public class IOTest {    public static void main(String[] args) throws IOException  {        //字符数组        char[] charArr = new char[]{'a', 'b', 'c'};        //通过内存中的字符数组,得到字符流        Reader reader = new CharArrayReader(charArr);        //改变数组charArr的元素值        charArr[0] = 'e';        //读取一个字符并打印        System.out.println((char)reader.read());//打印改变后的字符'e'        //关闭流        reader.close();    }}

PipedReader

可以通过PipedWriter和PipedReader创建字符流管道,线程间可以通过管道进行通信,注意:一定要同一个JVM中的两个线程;

PipedReader一般是要和PipedWriter配合使用的,其中一个线程通过PipedWriter往管道写数据,另一个线程通过管道读数据,注意读写都会阻塞线程,如下示例:

package io;import java.io.IOException;import java.io.PipedReader;import java.io.PipedWriter;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;public class IOTest {    public static void main(String[] args) throws IOException {        final PipedWriter pw = new PipedWriter();        final PipedReader pr = new PipedReader(pw);        ExecutorService es = Executors.newFixedThreadPool(2);        es.execute(new Runnable() {            @Override            public void run() {                try {                    pw.write("hello~");                } catch (IOException e) {                    e.printStackTrace();                }            }        });        es.execute(new Runnable() {            @Override            public void run() {                char[] cbuffer = new char[6];                try {                    // 会导致线程阻塞                    pr.read(cbuffer, 0, 6);                } catch (IOException e) {                    e.printStackTrace();                }                System.out.println(cbuffer);            }        });    }}

BufferedReader

这个字符流可以用来装饰其它字符输入流,可以为其它字符输入流提供字符缓冲区,避免每次从外部媒介中读取数据,这里用到了设计模式里的装饰器模式,可以参考我之前写的,

被装饰的字符流可以有更多的行为,比如readLine方法等;

举个使用的例子,读取外部文件:

package io;import java.io.BufferedReader;import java.io.FileReader;import java.io.IOException;public class IOTest {    public static void main(String[] args) throws IOException  {        //读取本地文件,得到字符流,这里设定缓冲区大小为10k        BufferedReader reader = new BufferedReader(new FileReader("C:\\test.txt"), 10 * 1024);        //读取一行        System.out.println(reader.readLine());        System.out.println(reader.readLine());        System.out.println(reader.readLine());        //关闭流        reader.close();    }}

LineNumberReader

继承BufferedReader,除了BufferedReader提供的功能外,还多了获取行号信息,

注意,LineNumberReader的setLineNumber方法并不能实现流的跳跃读取

举个例子

package io;import java.io.FileReader;import java.io.IOException;import java.io.LineNumberReader;public class IOTest {    public static void main(String[] args) throws IOException  {        //读取本地文件,得到字符流,这里设定缓冲区大小为10k        LineNumberReader reader = new LineNumberReader(new FileReader("C:\\test.txt"), 10 * 1024);                System.out.println(reader.getLineNumber());//打印当前行号        System.out.println(reader.readLine());//读取一行        System.out.println(reader.getLineNumber());        System.out.println(reader.readLine());//读取一行        //关闭流        reader.close();    }}

FilterReader

抽象类FilterReader是实现自定义过滤输入字符流的基类,从源码的实现上来看,仅仅只是简单覆盖了Reader中的所有方法,感觉没什么卵用,因为已经有一个抽象类Reader了;

PushbackReader

简单的说,PushbackReader字符流允许你在读取字符的过程中,通过调用unread方法往缓冲区插入字符,下次读取的时候,先从缓冲区读数据,缓冲区没数据再从流中读取;

该类同样使用了装饰器模式;

一般可以用PushbackReader完成读取回退功能,比如把之前读取的字符通过调用unread方法插入到缓冲区中,下次再读取的时候,就又可以读取到之前的数据了;

举个例子如下:

package io;import java.io.FileReader;import java.io.IOException;import java.io.PushbackReader;public class IOTest {    public static void main(String[] args) throws IOException {        // 读取本地文件,得到字符流,这里设定缓冲区大小为1024k        PushbackReader reader = new PushbackReader(new FileReader("C:\\test.txt"), 1024);        // 读取一个字符        char a = (char) reader.read();        System.out.println(a);        // 将读取的字符推回到流中        // 其实说的简单点,就是将字符a存到缓冲区中,下次读取的时候先从缓冲区读数据,缓冲区没数据再从流中读取        reader.unread(a);        // 重新读取之前的字(在缓冲区中)        System.out.println((char) reader.read());        // 从流中读取数据        System.out.println((char) reader.read());        // 关闭流        reader.close();    }}

StringReader

将字符串转为字符输入流,比较简单,看个使用例子如下:

package io;import java.io.IOException;import java.io.StringReader;public class IOTest {    public static void main(String[] args) throws IOException {        // 通过字符串,得到字符流        StringReader reader = new StringReader("hello~");        // 从流中读取数据        char[] cbuf = new char[6];        reader.read(cbuf, 0, 6);        System.out.println(cbuf);        // 关闭流        reader.close();    }}

 

本文转自风一样的码农博客园博客,原文链接:http://www.cnblogs.com/chenpi/p/5361658.html,如需转载请自行联系原作者
你可能感兴趣的文章
前端CSS预处理器Sass
查看>>
深入理解定时器系列第二篇——被誉为神器的requestAnimationFrame
查看>>
struts2.1 datetimepicker日期控件的使用(引用)
查看>>
poj2967
查看>>
C#项目关于HRMsys.exe”不包含适合于入口点的静态“Main”方法
查看>>
[Selenium] 操作页面元素等待时间
查看>>
暴力 BestCoder Round #46 1001 YJC tricks time
查看>>
ACM 2017 ACM-ICPC 亚洲区(南宁赛区)网络赛 B. Train Seats Reservation
查看>>
lua劈分字符串方法及实例
查看>>
HDU2222:Keywords Search——题解
查看>>
6. 使用Axis开发WebService程序
查看>>
引用 英语学习的六大原则
查看>>
Spring中ClassPathXmlApplicationContext类的简单使用
查看>>
java8的LocalDateTime真心好用(补充Period.between的大坑)
查看>>
XMLHelper类 源码(XML文档帮助类,静态方法,实现对XML文档的创建,及节点和属性的增、删、改、查)...
查看>>
装饰器叠加和有参装饰器
查看>>
基本位运算
查看>>
高精度计算
查看>>
[转] 投资策略及投资体系
查看>>
多张报表导出到一个多sheet页excel
查看>>