通过源码学Java基础:BufferedReader和BufferedWriter
准备写一系列Java基础文章,先拿Java.io下手,今天聊一聊BufferedReader和BufferedWriter
BufferedReader
BufferedReader继承Writer,本身的方法非常简单,其官方解释如下:
Reads text from a character-input stream, buffering characters so as to provide for the efficient reading of characters, arrays, and lines.
The buffer size may be specified, or the default size may be used. The default is large enough for most purposes.
简单翻译一下:
从流里面读取文本,通过缓存的方式提高效率,读取的内容包括字符、数组和行。
缓存的大小可以指定,也可以用默认的大小。大部分情况下,默认大小就够了。
1. 构造函数
BufferedReader有两个构造函数,其声明如下:
BufferedReader(Reader in)
Creates a buffering character-input stream that uses a default-sized input buffer.
BufferedReader(Reader in, int sz)
Creates a buffering character-input stream that uses an input buffer of the specified size.
一个是传一个Reader,另外一个增加了缓存的大小。
其真正的实现也很简单,反编译Java源码如下:
public BufferedWriter(Writer paramWriter)
{
this(paramWriter, defaultCharBufferSize);
}
public BufferedWriter(Writer paramWriter, int paramInt)
{
super(paramWriter);
if (paramInt <= 0) {
throw new IllegalArgumentException("Buffer size <= 0");
}
this.out = paramWriter;
this.cb = new char[paramInt];
this.nChars = paramInt;
this.nextChar = 0;
this.lineSeparator = ((String)AccessController.doPrivileged(new GetPropertyAction("line.separator")));
}
常见的初始化方法
BufferedReader br = new BufferedReader(new FileReader("d:/123.txt"));
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
第一个方法是读取一个文件;第二个方法是从标准输入读。
2. 主要方法
void close()
Closes the stream and releases any system resources associated with it.
void mark(int readAheadLimit)
Marks the present position in the stream.
boolean markSupported()
Tells whether this stream supports the mark() operation, which it does.
int read()
Reads a single character.
int read(char[] cbuf, int off, int len)
Reads characters into a portion of an array.
String readLine()
Reads a line of text.
boolean ready()
Tells whether this stream is ready to be read.
void reset()
Resets the stream to the most recent mark.
long skip(long n)
Skips characters.
提供了三种读数据的方法read、read(char[] cbuf, int off, int len)、readLine(),其中常用的是readLine。
a. read方法
Reads a single character.
这个方法从reader里面读一个字符,并向下移一位。如果读完了,会返回-1.
public void readTest() {
try {
BufferedReader br = new BufferedReader(new FileReader("d:/123.txt"));
for (;;) {
int i = br.read();
if (i == -1) {
break;
}
System.out.print((char) i);
}
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
b. read(char[] cbuf, int off, int len)方法
public void readCharTest() {
try {
BufferedReader br = new BufferedReader(new FileReader("d:/123.txt"));
char[] buf = new char[100];
br.read(buf);
System.out.print(String.valueOf(buf));
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
如上,先定义一个数组,然后读进数组就可以了。如果数组比内容少,则数组满了就不读了。当然,也可以指定数据的off和len,但一般不用。
c. readline方法
public void readline() {
try {
BufferedReader br = new BufferedReader(new FileReader("d:/123.txt"));
while (true) {
String str = br.readLine();
if (str == null) {
break;
}
System.out.println(str);
}
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
用null判断是否读完。
d. close方法
Closes the stream and releases any system resources associated with it. Once the stream has been closed, further read(), ready(), mark(), reset(), or skip() invocations will throw an IOException. Closing a previously closed stream has no effect.
用完流之后,一定要close掉。当然,放在finally里面更保险。
3. 其他
BufferedReader的子类包括FileReader, InputStreamReader。因此,这两个子类也有如上方法。
BufferedWriter
BufferedWriter继承自java.io.Writer。
Writes text to a character-output stream, buffering characters so as to provide for the efficient writing of single characters, arrays, and strings.
The buffer size may be specified, or the default size may be accepted. The default is large enough for most purposes.
1. 构造函数
BufferedWriter(Writer out)
Creates a buffered character-output stream that uses a default-sized output buffer.
BufferedWriter(Writer out, int sz)
Creates a new buffered character-output stream that uses an output buffer of the given size.
其源码如下:
public BufferedWriter(Writer paramWriter)
{
this(paramWriter, defaultCharBufferSize);
}
public BufferedWriter(Writer paramWriter, int paramInt)
{
super(paramWriter);
if (paramInt <= 0) {
throw new IllegalArgumentException("Buffer size <= 0");
}
this.out = paramWriter;
this.cb = new char[paramInt];
this.nChars = paramInt;
this.nextChar = 0;
this.lineSeparator = ((String)AccessController.doPrivileged(new GetPropertyAction("line.separator")));
}
用法
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
BufferedWriter bw = new BufferedWriter(new FileWriter("d:/1234.txt", true));
输出到标准输出或者输出到一个文件。
2. 主要方法
void close()
Closes the stream, flushing it first.
void flush()
Flushes the stream.
void newLine()
Writes a line separator.
void write(char[] cbuf, int off, int len)
Writes a portion of an array of characters.
void write(int c)
Writes a single character.
void write(String s, int off, int len)
Writes a portion of a String.
既然是writer,那主要是写数据。
a. write方法
private void writeTest() {
try {
BufferedWriter bw = new BufferedWriter(
new FileWriter("d:/1234.txt"));
bw.write("writeTest");
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
注意,BufferedWriter没有write(String s)或者write(char[] s)的定义,为什么还能直接bw.write("writeTest")呢。因为BufferedWriter的父类Writer实现了这个方法。不过,writer实际上也是调用了BufferedWriter的方法实现的。
public void write(String paramString, int paramInt1, int paramInt2)
throws IOException
{
synchronized (this.lock)
{
char[] arrayOfChar;
if (paramInt2 <= 1024)
{
if (this.writeBuffer == null) {
this.writeBuffer = new char['?'];
}
arrayOfChar = this.writeBuffer;
}
else
{
arrayOfChar = new char[paramInt2];
}
paramString.getChars(paramInt1, paramInt1 + paramInt2, arrayOfChar, 0);
write(arrayOfChar, 0, paramInt2);
}
}
其中write(arrayOfChar, 0, paramInt2)在Writer中是抽象方法,定义如下:
public abstract void write(char[] paramArrayOfChar, int paramInt1, int paramInt2)
throws IOException;
这个是标准的模板模式啊。
b. newLine方法
newLine方法实现了换行,其源码如下:
public void newLine()
throws IOException
{
write(this.lineSeparator);
}
代码很简单,只是写了一个换行符,那么换行符是什么呢?
this.lineSeparator = ((String)AccessController.doPrivileged(new GetPropertyAction("line.separator")));
不过,也有人说换行符有的时候不靠谱,不过我没遇到过。
在Java7之后,也可以这么写,当然,实际上是一样的。
System.lineSeparator()
c. flush方法
flush方法的说明是这样的
Flushes the stream.
也就是说会把内容flush进去,冲进去。
那什么时候用这个呢?答案就是,基本上不用。
先看看flush干了什么事情。
public void flush()
throws IOException
{
synchronized (this.lock)
{
flushBuffer();
this.out.flush();
}
}
就是调用了flushBuffer()方法。
那么close的时候干了什么事情呢?
public void close()
throws IOException
{
synchronized (this.lock)
{
if (this.out == null) {
return;
}
try
{
flushBuffer();
}
finally
{
this.out.close();
this.out = null;
this.cb = null;
}
}
}
注意,也调用了flushBuffer()。也就是说,只要你close了,就不用flush了。
而且,write也会flush,其代码如下:
public void write(int paramInt)
throws IOException
{
synchronized (this.lock)
{
ensureOpen();
if (this.nextChar >= this.nChars) {
flushBuffer();
}
this.cb[(this.nextChar++)] = ((char)paramInt);
}
}
那close和write都flush了,flush还有啥用呢?有人这么说:
In other words, relax - just write, write, write and close
通过源码学Java基础:BufferedReader和BufferedWriter的更多相关文章
- 通过源码学Java基础:InputStream、OutputStream、FileInputStream和FileOutputStream
1. InputStream 1.1 说明 InputStream是一个抽象类,具体来讲: This abstract class is the superclass of all classes r ...
- 通过源码分析Java开源任务调度框架Quartz的主要流程
通过源码分析Java开源任务调度框架Quartz的主要流程 从使用效果.调用链路跟踪.E-R图.循环调度逻辑几个方面分析Quartz. github项目地址: https://github.com/t ...
- 通过源码浅析Java中的资源加载
前提 最近在做一个基础组件项目刚好需要用到JDK中的资源加载,这里说到的资源包括类文件和其他静态资源,刚好需要重新补充一下类加载器和资源加载的相关知识,整理成一篇文章. 理解类的工作原理 这一节主要分 ...
- 通过源码了解Java的自动装箱拆箱
什么叫装箱 & 拆箱? 将int基本类型转换为Integer包装类型的过程叫做装箱,反之叫拆箱. 首先看一段代码 public static void main(String[] args) ...
- 通过源码安装PostgresSQL
通过源码安装PostgresSQL 1.1 下载源码包环境: Centos6.8 64位 yum -y install bison flex readline-devel zlib-devel yum ...
- 通过源码了解ASP.NET MVC 几种Filter的执行过程
一.前言 之前也阅读过MVC的源码,并了解过各个模块的运行原理和执行过程,但都没有形成文章(所以也忘得特别快),总感觉分析源码是大神的工作,而且很多人觉得平时根本不需要知道这些,会用就行了.其实阅读源 ...
- Linux下通过源码编译安装程序
本文简单的记录了下,在linux下如何通过源码安装程序,以及相关的知识.(大神勿喷^_^) 一.程序的组成部分 Linux下程序大都是由以下几部分组成: 二进制文件:也就是可以运行的程序文件 库文件: ...
- 通过源码了解ASP.NET MVC 几种Filter的执行过程 在Winform中菜单动态添加“最近使用文件”
通过源码了解ASP.NET MVC 几种Filter的执行过程 一.前言 之前也阅读过MVC的源码,并了解过各个模块的运行原理和执行过程,但都没有形成文章(所以也忘得特别快),总感觉分析源码是大神 ...
- 在centos6.7通过源码安装python3.6.7报错“zipimport.ZipImportError: can't decompress data; zlib not available”
在centos6.7通过源码安装python3.6.7报错: zipimport.ZipImportError: can't decompress data; zlib not available 从 ...
随机推荐
- POJ 3468 A Simple Problem with Integers(树状数组)
题目链接:http://poj.org/problem?id=3468 题意:给出一个数列,两种操作:(1)将区间[L,R]的数字统一加上某个值:(2)查询区间[L,R]的数字之和. 思路:数列A,那 ...
- EBS报表输出文件格式控制
具体使用方法:1.添加用户参数p_conc_request_id2.在BeforeReport trigger中添加srw.user_exit('FND SRWINIT'); 和Af ...
- poj 1054 The Troublesome Frog (暴力搜索 + 剪枝优化)
题目链接 看到分类里是dp,结果想了半天,也没想出来,搜了一下题解,全是暴力! 不过剪枝很重要,下面我的代码 266ms. 题意: 在一个矩阵方格里面,青蛙在里面跳,但是青蛙每一步都是等长的跳, 从一 ...
- 11月下旬poj其他题
poj1000,poj1003,poj1004,poj1064,poj1218 水题 poj1012:0<k<14——漂亮的打表 poj1651:与能量项链很像的dp poj1159:回文 ...
- Qt之进程间通信(共享内存)
简述 上一节中,我们分享下如何利用Windows消息机制来进行不同进程间的通信.但是有很多局限性,比如:不能跨平台,而且必须两个进程同时存在才可以,要么进程A发了消息谁接收呢? 下面我们来分享另外一种 ...
- bzoj1797: [Ahoi2009]Mincut 最小割
最大流+tarjan.然后因为原来那样写如果图不连通的话就会出错,WA了很久. jcvb: 在残余网络上跑tarjan求出所有SCC,记id[u]为点u所在SCC的编号.显然有id[s]!=id[t] ...
- Delegate 委托复习(-) 委托的基本概念
1. 声明一个delegate对象,它应当与你想要传递的方法具有相同的参数和返回值类型. 声明一个代理的例子: public delegate int MyDelegate(stri ...
- UVA 820 Internet Bandwidth 因特网宽带(无向图,最大流,常规)
题意:给一个无向图,每条边上都有容量的限制,要求求出给定起点和终点的最大流. 思路:每条无向边就得拆成2条,每条还得有反向边,所以共4条.源点汇点已经给出,所以不用建了.直接在图上跑最大流就可以了. ...
- highcharts 柱状图动态设置数据应用实例
<div id="container" style="min-width:700px;height:400px"></div> #jav ...
- java web 学习十六(JSP指令)
一.JSP指令简介 JSP指令(directive)是为JSP引擎而设计的,它们并不直接产生任何可见输出,而只是告诉引擎如何处理JSP页面中的其余部分. 在JSP 2.0规范中共定义了三个指令: pa ...