字符输入流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

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

http://www.cnblogs.com/chenpi/p/5173818.html

被装饰的字符流可以有更多的行为,比如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();
}
}

字符输入流Reader简要概括的更多相关文章

  1. 字符输出流Writer简要概括

    偷个懒,直接参考上篇字符输入流Reader的形式,其实Reader和Writer本来就大同小异: 字符输出流Writer 本篇将对JAVA I/O流中的字符输出流Writer做个简单的概括: 总得来说 ...

  2. [19/03/31-星期日] IO技术_四大抽象类_字符流( 字符输入流 Reader、 字符输出流 Writer )(含字符缓冲类)

     一.概念 Reader Reader用于读取的字符流抽象类,数据单位为字符. int read(): 读取一个字符的数据,并将字符的值作为int类型返回(0-65535之间的一个值,即Unicode ...

  3. 00091_字符输入流Reader

    1.字符输入流Reader (1)字符输入流Reader我们读取拥有中文的文件时,使用的字节流在读取,那么我们读取到的都是一个一个字节: (2)只要把这些字节去查阅对应的编码表,就能够得到与之对应的字 ...

  4. Java 之 字符输入流[Reader]

    一.字符输入流 java.io.Reader 抽象类是表示用于读取字符流的所有类的超类,可以读取字符信息到内存中. 它定义了字符输入流的基本共性功能方法. public void close() :关 ...

  5. 字符输入流Reader类和FileReader和字符输入流读取字符数据

    java.io.Reader:字符输入流,是字符输入流的最顶层的父类,定义了一些共性的成员方法,是一个抽象类 共性成员方法: int read();读取单个字符并返回 int read(char[] ...

  6. JAVA I/O 字符输出流简要概括

    偷个懒,直接参考上篇字符输入流Reader的形式,其实Reader和Writer本来就大同小异: 字符输出流Writer 本篇将对JAVA I/O流中的字符输出流Writer做个简单的概括: 总得来说 ...

  7. java IO之字节流和字符流-Reader和Writer以及实现文件复制拷贝

    接上一篇的字节流,以下主要介绍字符流.字符流和字节流的差别以及文件复制拷贝.在程序中一个字符等于两个字节.而一个汉字占俩个字节(一般有限面试会问:一个char是否能存下一个汉字,答案当然是能了,一个c ...

  8. Java IO流详解(四)——字符流Reader和Writer

    前面一章介绍了字节流的使用,提到了字节流在处理utf-8编码的中文可能会出现乱码的情况(其他编码的中文同样会出现乱码),所以Java针对这一情况提供了字符流. 但是字符流只能处理字符,不能用来处理 . ...

  9. Reader字符输入流和InputStreamReader和FileReader

    1.FileReader  extends InputStreamReader extends Reader 其中,Reader字符输入流和InputStreamReader和FileReader为字 ...

随机推荐

  1. iOS阶段学习第二天笔记(数据类型与进制)

    iOS学习(C语言)知识点整理笔记 1.C语言32个关键字 一.存储相关 1)auto 声明自动变量 2)register 声明寄存器变量 3)volatile 声明的变量在程序执行过程中可能被隐含的 ...

  2. 【Linux_Fedora_应用系列】_2_如何安装视频播放器和视频文件解码

    在前面的一篇博文中,我们进行了音乐播放器的安装和解码器的安装.[Linux_Fedora_应用系列]_1_如何安装音乐播放器和mp3解码 这里我们来进行视频播放器的安装.我们还是通过yum方式安装. ...

  3. 初识 PHPunit stub 模拟返回数据

    这是这段时间以来结合 PHPunit 文档和大牛们的讲解,想记录下自己学习到的知识,未来参考补充,完善学到的东西 我们一般使用单测对公司业务里的代码进行测试,他会帮忙找到你的一个个小小的思考不够全面的 ...

  4. Verilog学习笔记设计和验证篇(五)...............层次化事件队列

    详细的了解层次化事件队列有助于理解Verilog的阻塞赋值和非阻塞赋值功能.所谓层次化事件队列指的是用于调度仿真时间的不同Verilog事件队列.在IEEE的5.3节中定义了层次化事件队列在逻辑上分为 ...

  5. 【FOL】第六周

    最近太忙,三周(第四.五.六周)一起记录一下. 1.完成了键盘的输入,顺便把之前鼠标输入改了一下(最早是在渲染循环里面处理鼠标事件) 2.UI控件方面,做了个Edit控件,把之前的Label.Imag ...

  6. AWS CloudFront CDN直接全站加速折腾记The request could not be satisfied. Bad request

    ERROR The request could not be satisfied. Bad request. Generated by cloudfront (CloudFront) Request ...

  7. 茎叶图(stem)

    介绍 茎叶图(Stem-and-Leaf display)又称“枝叶图”,由统计学家约翰托奇( Arthur Bowley)设计,它的思路是将数组中的数按位数进行比较,将数的大小基本不变或变化不大的位 ...

  8. 使用Javascript来编写贪食蛇(零基础)

      引用的东西都很基础,注释也很多,这里就不多说了. <head> <meta http-equiv="Content-Type" content="t ...

  9. Android无线调试

    方法一: 1. 使用USB数据线连接设备. 2. 命令输入adb tcpip 5555 ( 5555为端口号,可以自由指定). 3. 断开 USB数据,此时可以连接你需要连接的|USB设备. 4. 再 ...

  10. JSON解析实例——使用Json-lib

    JSON解析实例——使用Json-lib Json-lib下载及使用 本文介绍用一个类库进行JSON解析. 工具下载地址:http://sourceforge.net/projects/json-li ...