BufferedReader和BufferedWriter简介

为了提高字符流读写的效率,引入了缓冲机制,进行字符批量的读写,提高了单个字符读写的效率。BufferedReader用于加快读取字符的速度,BufferedWriter用于加快写入的速度

BufferedReader和BufferedWriter类各拥有8192个字符的缓冲区。当BufferedReader在读取文本文件时,会先尽量从文件中读入字符数据并放满缓冲区,而之后若使用read()方法,会先从缓冲区中进行读取。如果缓冲区数据不足,才会再从文件中读取,使用BufferedWriter时,写入的数据并不会先输出到目的地,而是先存储至缓冲区中。如果缓冲区中的数据满了,才会一次对目的地进行写出。

BufferedReader
BufferedReader是为了提供读的效率而设计的一个包装类,它可以包装字符流。可以从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。

构造方法
方法 描述
BufferedReader(Reader in) 创建一个使用默认大小输入缓冲区的缓冲字符输入流。
BufferedReader(Reader in, int sz) 创建一个使用指定大小输入缓冲区的缓冲字符输入流。
成员方法
方法 描述
int read() 读取单个字符。
int read(char[] cbuf, int off, int len) 将字符读入数组的某一部分。
String readLine() 读取一个文本行。
long skip(long n) 跳过字符。
boolean ready() 判断此流是否已准备好被读取。
void close() 关闭该流并释放与之关联的所有资源。
void mark(int readAheadLimit) 标记流中的当前位置。
boolean markSupported() 判断此流是否支持 mark() 操作(它一定支持)。
void reset() 将流重置到最新的标记。
读取文件实例
读取文件: 一个字符一个字符的读取
int read()方法,每次可以读取到一个字符(以int 类型表示),不过因为返回的是int类型的,所以要强制类型转换成char类型才能打印该字符。

public static void printByFileReader(String filePath) throws IOException
{
BufferedReader reader=new BufferedReader(
new FileReader(filePath)
);
if(!reader.ready())
{
System.out.println("文件流暂时无法读取");
return;
}
int result=0;
while((result=reader.read())!=-1)
{
//因为读取到的是int类型的,所以要强制类型转换
System.out.print((char)result);
}
reader.close();
}

读取文件:一个数组一个数组的读取
int read(char[] cbuf, int off, int len)方法,每次读取len个字符放到字符数组cbuf中,从数组cbuf的下表off开始放,返回的是每次读取的字符个数。

public static void printByFileReaderChars(String filePath) throws IOException
{
BufferedReader reader=new BufferedReader(
new FileReader(filePath)
);
if(!reader.ready())
{
System.out.println("文件流暂时无法读取");
return;
}
int size=0;
char[] cbuf=new char[20];
while((size=reader.read(cbuf, 0, cbuf.length))!=-1)
{
System.out.print(new String(cbuf,0,size));
}
reader.close();
}

读取文件:一行一行的读取
String readLine()这个方法一次可以读取一个文本行,返回的直接就是这一行的字符串,如果读到行尾了就返回null。

public static void printByFileReaderLine(String filePath) throws IOException
{
BufferedReader reader=new BufferedReader(
new FileReader(filePath)
);
if(!reader.ready())
{
System.out.println("文件流暂时无法读取");
return;
}
int size=0;
String line;
while((line=reader.readLine())!=null)
{
System.out.print(line+"\n");
}
reader.close();
}

需要注意的是:reader.readLine()方法返回的一行字符中不包含换行符,所以输出的时候要自己加上换行符。

BufferedReader比FileReader高级的地方在于这个,FileReader能一次读取一个字符,或者一个字符数组。而BufferedReader也可以,同时BufferedReader还能一次读取一行字符串。同时,BufferedReader带缓冲,会比FileReader快很多。

但是FileReader使用项目的编码来读取解析字符,不能指定编码,可能会出现编码问题,如果要指定编码可以使用包装InputStreamReader的BufferedReader。这样兼顾效率和编码。

测试上述方法:

public static void main(String[] args) throws IOException
{
String fileutf8="utf8.txt";
String filegbk="gbk.txt";
//一个字符一个字符的读取
printByFileReader(filegbk);
System.out.println("\n---------------------------------------");
//一个字符数组一个字符数组的读取
printByFileReaderChars(filegbk);
System.out.println("\n---------------------------------------");
//一行一行的读取
printByFileReaderLine(filegbk);
System.out.println("#########################################");
//一个字符一个字符的读取
printByFileReader(fileutf8);
System.out.println("\n---------------------------------------");
//一个数组一个数组的读取
printByFileReaderChars(fileutf8);
System.out.println("\n---------------------------------------");
//一行一行的读取
printByFileReaderLine(fileutf8);
}

运行结果:

gbk file
这里是一句中文
---------------------------------------
gbk file
这里是一句中文
---------------------------------------
gbk file
这里是一句中文
#########################################
utf-8 file
杩欓噷鏄竴鍙ヤ腑鏂?
---------------------------------------
utf-8 file
杩欓噷鏄竴鍙ヤ腑鏂?
---------------------------------------
utf-8 file
杩欓噷鏄竴鍙ヤ腑鏂?

可以看到包装FileReader的BufferedReader在读取文件时候如果文件的编码和项目的编码不一样的时候,会出现乱。

乱码问题
使用包装InputStreamReader的BufferedReader读取文件

String file = "utf8.txt";
BufferedReader reader = new BufferedReader(
new InputStreamReader(new FileInputStream(file), "utf-8"));
char[] cbuf=new char[20];
int size;
while((size=reader.read(cbuf, 0, cbuf.length))!=-1)
{
System.out.println(new String(cbuf,0,size));
}

运行结果:

utf-8 file
这里是一句中文

这里要弄清楚的是BufferedReader只负责读到它的内部缓冲区中,而解码的工作是InputStreamReader完成的。

BufferedWriter
BufferedWriter的API:

构造函数:
方法 描述
BufferedWriter(Writer out) 创建一个缓冲字符输出流,使用默认大小的输出缓冲区
BufferedWriter(Writer out, int sz) 创建一个缓冲字符输出流,使用给定大小的输出缓冲区
成员方法
方法 描述
void write(int c) 写入单个字符。
void write(char[] cbuf, int off, int len) 写入字符数组的某一部分。
void write(String s, int off, int len) 写入字符串的某一部分。
void newLine() 写入一个行分隔符。
void close() 关闭此流,但要先刷新它。
void flush() 刷新该流的缓冲。
写文件实例
使用上述三个写方法写文件:一个字符一个字符的复制文件

public static void main(String[] args) throws IOException
{
BufferedWriter writer=new BufferedWriter(new FileWriter("静夜思.txt"));
char ch=‘床‘;
//写入一个字符
writer.write(ch);
String next="前明月光,";
char[] nexts=next.toCharArray();
//写入一个字符数组
writer.write(nexts,0,nexts.length);
//写入换行符
writer.newLine();//写入换行符
String nextLine="疑是地上霜。";
//写入一个字符串。
writer.write(nextLine);
//关闭流
writer.close();
}

运行结果,静夜思.txt:

床前明月光,
疑是地上霜。

应用:复制文本文件
逐个字符复制文件

static void copyByChar(String srcFile, String destFile) throws IOException
{
BufferedReader reader = new BufferedReader(new FileReader(srcFile));
BufferedWriter writer = new BufferedWriter(new FileWriter(destFile));
int ch=0;
//读取一个字符
while ((ch = reader.read()) != -1)
{
//写入一个字符
writer.write(ch);
}
reader.close();
writer.close();
}

逐个字符数组复制文件

static void copyByCharArray(String srcFile, String destFile) throws IOException
{
BufferedReader reader = new BufferedReader(new FileReader(srcFile));
BufferedWriter writer = new BufferedWriter(new FileWriter(destFile));
int size=0;
char[] cbuf=new char[20];
//读取一个字符数组
while ((size = reader.read(cbuf)) != -1)
{
//读入多少写入多少
writer.write(cbuf,0,size);
}
reader.close();
writer.close();
}

按行复制文件

static void copyByLine(String srcFile,String destFile) throws IOException
{
BufferedReader reader=new BufferedReader(new FileReader(srcFile));
BufferedWriter writer=new BufferedWriter(new FileWriter(destFile));
String line;
//BufferedReader读取一行的时候返回的字符串中不包括换行符
//如果有一行字符就返回该行字符串,没有就返回null
while((line=reader.readLine())!=null)
{
writer.write(line);
writer.newLine();//写换行符
}
reader.close();
writer.close();
}

需要注意的是,BufferedReader的readLine()读取一行的时候返回的字符串没有换行符,所以,复制的时候写文件是我们好多写入一个换行符,使用writer.newLine()方法即可。

测试:

public static void main(String[] args) throws IOException
{
String from = "gbk.txt";
String to = "gbk_copy.txt";
String to1 = "gbk_copy1.txt";
String to2 = "gbk_copy2.txt";
copyByChar(from, to);
copyByCharArray(from, to1);
copyByLine(from, to2);
}

源文件gbk.txt:
运行结果:
gbk_copy.txt

gbk file
这里是一句中文

gbk_copy1.txt

gbk file
这里是一句中文

gbk_copy2.txt

gbk file
这里是一句中文

bug:按行复制的时候多写换行符
细心的朋友可能发现,按行复制的时候,复制的文件会莫名其妙的在文件后面多了一个换行符。这是因为我们每次都在读到的字符串后面写一个换行符。
解决办法:在读到的字符串前面写换行符,这样出现新的问题,就是在文件开头多出了一个空行,所以加入控制语句,在第一行不写入换行符,第二行后再写。

static void copyByLine(String srcFile,String destFile) throws IOException
{
BufferedReader reader=new BufferedReader(new FileReader(srcFile));
BufferedWriter writer=new BufferedWriter(new FileWriter(destFile));
String line;
//BufferedReader读取一行的时候返回的字符串中不包括换行符
//如果有一行字符就返回该行字符串,没有就返回null
boolean flag=false;
while((line=reader.readLine())!=null)
{
if(!flag)
{
flag=true;
writer.write(line);
}
else
{
writer.newLine();//写换行符
writer.write(line);
}

}
reader.close();
writer.close();
}

这样复制的文件就不会多谢换行符了,保证复制的文件和源文件是一模一样的。

bug:乱码问题
因为我们使用的是包装FileReader的BufferedReader,包装FileWriter的BufferedWriter。所以读字符,写字符的时候使用的是默认的字符编码读写的。所以读写文件的时候会出现乱码,可以使用包装InputStreamReader的BufferedReader,包装OutputStreamWriter的BufferedWriter来复制文件,这样就可以支持各种字符编码。

实例:gbk编码的文件复制到utf8编码的文件中:

static void copyByLineEncoding(String srcFile, String srcEncoding, String destFile,
String destEncoding)
{
BufferedReader reader = null;
BufferedWriter writer = null;
try
{
reader = new BufferedReader(new InputStreamReader(
new FileInputStream(srcFile), srcEncoding));
writer = new BufferedWriter(new OutputStreamWriter(
new FileOutputStream(destFile), destEncoding));
char[] charArray = new char[512];
int size;
while ((size = reader.read(charArray, 0, charArray.length)) != -1)
{
writer.write(charArray, 0, size);
}

} catch (UnsupportedEncodingException | FileNotFoundException e)
{
e.printStackTrace();
} catch (IOException e)
{
e.printStackTrace();
} finally
{
if (writer != null)
{
try
{
writer.close();
} catch (IOException e)
{
e.printStackTrace();
}
}
if (reader != null)
{
try
{
reader.close();
} catch (IOException e)
{
e.printStackTrace();
}
}
}
}

main方法:

public static void main(String[] args) throws IOException
{
String from = "gbk.txt";
String to = "copyto_utf8.txt";
copyByLineEncoding(from,"gbk",to,"utf-8");
}

源文件gbk.txt(gbk编码):

gbk file
这里是一句中文

目标文件copyto_utf8.txt:

utf-8 file
杩欓噷鏄竴鍙ヤ腑鏂?

乱码是正常的,因为我们的工程目录用的gbk编码,把copyto_utf8.txt编码显示就好了:

utf-8 file
这里是一句中文

所以使用包装InputStreamReader的BufferedReader,包装OutputStreamWriter的BufferedWriter来复制文件的好处就是可以指定复制文件的时候使用的字符编码,例如上面的复制操作,从gbk编码的文件中读取,然后写入到utf8编码的文件中去。
————————————————
版权声明:本文为CSDN博主「蓝蓝223」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_21808961/article/details/81561464

原文地址:https://www.cnblogs.com/cangqinglang/p/11450863.html

时间: 2024-10-13 11:49:36

BufferedReader和BufferedWriter简介的相关文章

J06-Java IO流总结六 《 BufferedReader和BufferedWriter 》

1. 概念简介 与字节缓冲流BufferedInputStream和BufferedOutputStream对应的,我们还有字符缓冲流BufferedReader和BufferedWriter,顾名思义,它们是带有字符缓冲区的字符输入输出流,原理跟字节缓冲流一样,这两个流也是使用装饰模式对底层字符输入流进行了包装,并通过字符缓冲区来提高I/O效率,这里不再详细说明.唯一需要注意的是,相对于它们的父类,则两个流分别都新增了一些自己的方法,如下所示: BufferedReader新增方法: Stri

理解IO流:InputStream和OutputStream,FileInputStream和FileOutputStream,Reader和Writer,FileReader和FileWriter,BufferedInputStream 和 BufferedOutputStream, BufferedReader 和 BufferedWriter,转换流

/* * 1.理解 "流" ? * 动态性.连续性.方向性. * * 2.在java语言中,将数据的输入/输出称之为 IO流. IO流的分类: * 1) 从方向分: 输入流 , 输出流. (参照计算机的内存) * 将数据送到内存中去称之为输入流.反之,称之为输出流. * * 2) 从处理单位来分: 字节流(8位二进制数据), 字符流(16位二进制数据). * * 3) 从是否有数据源来分: 节点流(有数据源), 处理流(必须套在节点流上). * * 3.在Java语言中,所有流类均来自

IO流(二)——BufferedReader和BufferedWriter

BufferedReader和BufferedWriter 字符流的缓冲区:缓冲区的而出现提高了对数据的读写效率对应类:BufferedWriter  BufferedReader缓冲区要结合流才可以使用,在流的基础上对流的功能进行了增强.实际上BufferedReader和BufferedWriter是对FileReader和FileWriter的装饰模式.BufferedWriter: bufw.newLine(); public class BufferedWriterDemo { pri

JAVA之IO技术BufferedReader,BufferedWriter的缓冲区技术的使用和原理

BufferedReader: package ioTest.io2; /* * BufferedReader:该缓冲区提供了一个一次读一行的方法 * readline(); * * 加入缓冲区技术的优点是什么呢? * 原来我是读一个字符取一个字符,现在变成我读一行字符,将其放在数组中,然后再取. * 这样是不是提高了效率.实际上BufferedReader类底层实现的原理,就是利用了数组. */ import java.io.BufferedReader; import java.io.Fil

BufferedReader和BufferedWriter

BufferedReader和BufferedWriter 读书笔记 OSIDEA . 1. java.io.BufferedReader和java.io.BufferedWriter类各拥有8192字符的缓冲区.当BufferedReader在读取文本文件时,会先尽量从文件中读入字符数据并置入缓冲区,而之后若使用read()方法,会先从缓冲区中进行读取.如果缓冲区数据不足,才会再从文件中读取,使用BufferedWriter时,写入的数据并不会先输出到目的地,而是先存储至缓冲区中.如果缓冲区中

Java-IO流之BufferedReader 和BufferedWriter的使用和原理

BufferedReader和BufferedWriter出现的目的是为了对FileReader以及FileWriter的读写操作进行增强,而怎么增强呢,原理类似于使用StringBuilder,是把数据先放入他们的一个char数组中,然后再操作char数组. 使用缓冲区的字符流是使用了装饰着模式对FileReader等进行功能上的增强,装饰者模式与继承都可以实现功能上的增强,但是装饰者可以做得更加的灵活,也不会使继承树变得太过复杂. 以下是BufferedWriter源码的一小部分 publi

BufferInputStream、BufferOutputStream、BufferedReader、BufferedWriter、Java代码使用BufferedReader和BufferedWriter实现文本文件的拷贝

BufferInputStream和BufferOutputStream的特点: 缓冲字节输入输出流,缓冲流是处理流,它不直接连接数据源/目的地,而是以一个字节流为参数,在节点流的基础上提供一些简单操作. 先说不带缓冲流的工作原理吧,它读取到一个字节/字符,就向用户指定的路径写出去,读一个写一个,所以就慢了,带缓冲流的工作原理,读取到一个字节/字符,先不输出,等凑足了缓冲的最大容量后一次写出去,从而提高了工作效率. 优点:减少对硬盘的读取次数,降低对硬盘的损耗. 附: import java.i

java基础知识回顾之javaIO类---BufferedReader和BufferedWriter

使用了装饰设计模式:此类的设计是为了提高流操作数据的效率.思想就是定义容器将数据进行临时存储,对于缓冲区对象,其实就是将这个容器进行了分装,并提供了更高效的操作方法. 原理: 1,使用流的read方法从源中读取一批数据存储到缓冲区的数组中. 2,通过计数器记录住存储的元素个数. 3,通过数组的角标来获取数组中的元素(从缓冲区中取数据). 4,指针会不断的自增,当增到数组长度,会归0.计数器会自减,当减到0时,就在从源拿一批数据进缓冲区. BufferReader: package com.lp.

Java之IO(十一)BufferedReader和BufferedWriter

转载请注明源出处:http://www.cnblogs.com/lighten/p/7074488.html 1.前言 按照字节流的顺序一样,字符流也提供了缓冲字符流,与字节流不同,Java虽然提供了FilterReader和FilterWriter类,但是缓冲字符流没有继承者两个类,而是直接继承了Reader和Writer类. 2.BufferedReader 构造函数接受一个Reader和一个缓冲字符数量,默认8192. read方法不但使用了同步锁,还采取了for(;;)形式.nextCh