Java IO流理解指南(三)字符流

深入理解Java中IO流的使用技巧

Posted by yourzeromax on April 20, 2018

什么是字符流

距离发布上一篇文章过去了一段时间- -,有些不好意思,但影响不大哈~

开始说正题啦,如果读者忘记了字节流和字符流的关系和差异,可以回看上一篇系列教程,

所谓字符流,顾名思义,就是在Java中用来传输字符所用到的相关类,虽然计算机存储和传输的都是二进制数据,但是字符流在传输过程中进行了相应的一些封装操作,使得本来二进制的数据可以按照人类习惯的样子当成一个个字符来进行处理。在Java.io包中,这些专门处理字符的都是以Reader或者Writer为基础派生的系列类,一个是输入流,一个是输出流。

一般来说,在Java编程中对字符char进行处理,主要用到以下几种流:

  • 抽象基础流(Reader/Writer)
  • 输入输出转换流(InputStreamReader/OutputStreamWriter)
  • 字符数组流(charArrayReader/charArrayWriter)
  • 文件字符流(FileReader/FileWriter)
  • 缓冲字符流(BufferedReader/BufferedWriter)

除此之外,还有一个不太常用的装饰字符流(PrintWriter)

抽象基础流(Reader/Writer)

和字节流中的InputStream 和 OutputStream 一样,Reader和Writer也是抽象类,只提供了一系列用于字符流处理的接口,并不能直接使用,它们的方法与类 InputStream 和 OutputStream类似,只不过其中的参数换成字符或字符数组,在使用过程中都使用自带的抽象子类。
首先来看看Reader提供的抽象方法:

方法 返回值 描述
close() void 关闭流
mark (int limit) void 设置标记,标记在limit个字符前有效
markSupported() boolean 查询是否mark
read() int 读取一个字符返回一个整型。遇到文件尾时返回 -1
read(char[] buf, int off,int len) int 从off开始读取len个字符存储到buf数组中
ready() boolean 是否准备好读取
reset() void 重置输入指针到先前设立的标记处
skip(long n) long 跳过 n 个输入字符,返回跳过的字符

再来看看Writer提供的抽象方法:

方法 返回值 描述
close() void 关闭输出流。关闭后的写操作会产生 IOException 异常
flush() void 刷新输出缓冲区
write(char[] cbuf) void 向一个流写入一个完整的字符数组
write(char[] cbuf, int off,int len) void 向调用的的输出流写入数组 buffer 以 offset 为起点的 len 个字符区域内的内容
write(int c) void 输出单个字符,int类型低16位有效
write(String str) void 向输出流写字符串 str
write(String str, int off, int len) void 输出数组 str 中 以 offset 为起点的长度为 len 个字符区域内的内容

单从这些方法来看还是非常简单的,需要熟练掌握。

输入输出转换流(InputStreamReader/OutputStreamWriter)

其实这个类型的流是用的最为频繁的流,他直接继承自抽象基础流,使用方法也非常简单:

public class IoSteamUtils {

    public static void input(){
          InputStreamReader inr = new InputStreamReader(new FileInputStream("input.txt"));
        char[] chs = new char[100];
        inr.read(chs);
        System.out.println(chs);
        inr.close();
    }
    
    public static void output(){
        OutputStreamWriter ow = new OutputStreamWriter(new FileOutputStream("output.txt"));
        ow.write("hello word");
        ow.close();
    }
}

文件字符流(FileReader/FileWriter)

文件字符流也没什么难度,但是它比较特殊,因为和它对接的对象是File类对象,所以它的构造函数比较特殊:

``` public FileReader(String fileName) throws FileNotFoundException { super(new FileInputStream(fileName)); } public FileReader(File file) throws FileNotFoundException { super(new FileInputStream(file)); }

public FileWriter(String fileName) throws IOException { super(new FileOutputStream(fileName)); } public FileWriter(String fileName, boolean append) throws IOException { super(new FileOutputStream(fileName, append)); } public FileWriter(File file) throws IOException { super(new FileOutputStream(file)); }

必须要指明对接的File信息,其他的操作和抽象基础类提供的方法一样。  

# 缓冲字符流(BufferedReader/BufferedWriter)
缓冲字符流需要单独提出来说一下,并且也希望读者能够重视它,因为它可以明显地优化流的传输效率,在计算机中,进行硬盘文件读写操作的过程由于CPU工作频率和硬盘工作频率差别甚大,如果不采用缓冲字符流而进行直接的传输,必定会降低CPU工作频率来保持一致,缓冲字符流的功能就是先将多个字符流数据载入内存之中,再统一进行处理,这样的话,CPU就不必被硬盘而拖累了。
如下代码:

public class IoSteamUtils { public static void bufferRead(){ BufferedReader bins = new BufferedReader(new FileReader(“hello.txt”)); BufferedWriter bws = new BufferedWriter(new FileWriter(“hello.txt”,true)); int x; while ((x = bins.read()) != -1){ System.out.println((char)x); bws.write(x); } } }

```

总结

以上的内容就是字符流的介绍,进行对比学习能够加强对知识的记忆,而字节流和字符流虽然有较大差异,但是在设计理念和接口定义方面也有很多相同之处,Java流是一个非常重要的概念,熟能生巧,按照博主提供的思路,相信大家也会完全掌握它的。

欢迎大家访问
我的博客