第3节:Reader和Writer

上一节我们讲了文件流。当我们读取数据时遇到了一些问题,就是我们写入文件的是一个个的字符,但是我们读出来的却是一个个的字节。后来我们通过String类的带byte数组类型的构造方法,将其转换成了字符。那我们要问了,有没有一种办法,让我读出来的就是字符,而不需要我自己手动转呢?还真有!输入输出流的家族非常的庞大,我并不想在这里展示它的家族体系,因为没有意义。我想通过一篇讲一种流的方式,最后再总结它们的家族体系,这样思路会清晰的多。所以,这一篇我们讲字符流。

输入流


Java提供了Reader作为字符的输入流。它也在jdk的java.io包下,我们先来看看它是如何定义的:

public abstract class Reader implements Readable, Closeable {}

这是Reader的类定义。和InputStream一样,它也是抽象的。我们不可以直接用它,必须得创建一个子类继承它,实现它定义的抽象方法才行。我们来看看它都有哪些抽象的方法:

// 从cbuf的off索引处开始,读取len个字符到cbuf,返回读取到的字符数
abstract public int read(char cbuf[], int off, int len) throws IOException;

// 关闭输入流
abstract public void close() throws IOException;

read方法和InputStream的read方法差不多,不同的是InputStream读取的是字节,而Reader读取的是字符。close方法是用来关闭输入流的。我不知道大家对字节和字符的概念是不是清晰的,我大概的讲一下吧。字节,标准的byte,读取的数是一个数字,而且范围在-128到127之间;而字符不一定,它因码表而异。例如我们常见的ASCII码表,它每个字符占1个字节。而我们中国使用的是GBK编码(国标扩展码)。GBK编码中,一个中文汉字占2个字节,也就是说,如果我们传输过来的是2个字节,按照ASCII表来解码的话,可以得到两个拉丁字符;而如果按照GBK表来解码的话,只能得到一个中文汉字。这里就是关于字节和字符的知识补充了。

我们再看看它都提供了哪些非抽象方法吧!

// 将字符读取到CharBuffer里,返回读取到的字符数
public int read(java.nio.CharBuffer target) throws IOException {}

// 读取一个字符,返回该字符在码表的索引值
public int read() throws IOException {}

// 将数据读取到cbuf数组,返回读取到的字符数
public int read(char cbuf[]) throws IOException {}

// 跳过n个字符
public long skip(long n) throws IOException {}

// 为输入流的当前位置打一个标记
public void mark(int readAheadLimit) throws IOException {}

// 重置索引到标记位置
public void reset() throws IOException {}

这些方法和InputStream中的都差不多,无非就是字符和字节的区别,这里就不再赘述。

输出流


同样的,有进就有出。Java提供了Writer类供我们对字符进行写操作。我们看看Writer是如何定义的吧!

public abstract class Writer implements Appendable, Closeable, Flushable {}

它也是个抽象类。看看它都有哪些抽象方法!

// 将cbuf中的数据从off开始,写入len个字符
abstract public void write(char cbuf[], int off, int len) throws IOException;

// 将流数据写入目的地
abstract public void flush() throws IOException;

// 关闭输出流
abstract public void close() throws IOException;

还用解释吗?完全不需要!只要是吸收了前两节中讲的内容,这些东西完全能理解。再来看看他都提供了哪些非抽象方法!

// 写入码表下,c索引处的字符
public void write(int c) throws IOException {}

// 写入字符数组
public void write(char cbuf[]) throws IOException {}

// 写入字符串
public void write(String str) throws IOException {}

// 从字符串的off索引处开始,写入len个字符
public void write(String str, int off, int len) throws IOException {}

// 写入字符序列,返回当前对象
public Writer append(CharSequence csq) throws IOException {}

// 从字符序列的off索引处开始,写入len个字符,返回当前对象
public Writer append(CharSequence csq, int start, int end) throws IOException {}

// 写入一个字符,返回当前对象
public Writer append(char c) throws IOException {

前面4个方法我们都很熟悉,和OutputStream差不多,不同的是这里写入字符。后面三个方法写入的是字符序列对象,其返回的是当前对象,它的意思是支持我们链式调用。另外,如果对象为空,就会写入null这个字符串。

这两个流,对于我们来说理解起来完全没有压力,因为有了前两节的基础。现在,我们学到的IO流家族体系应该是这样的!

IO流家族体系


转载于:https://my.oschina.net/u/3962062/blog/3097826

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值