1、字符缓冲流基本介绍
缓冲区的出现提高了IO流对数据的读写效率,但缓冲区仅具备提高效率的功能,不具备读或写的功能,因此必须要结合IO流才可以使用,实际上是在IO流本身的基础上对IO流的功能进行了增强。
缓冲区对应字符流的类:
BufferedWriter:只能提高效率,不能进行写入操作
BufferedReader:只能提高效率,不能进行读取操作
2、使用缓冲输出流实现对文件的写入
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
public class Demo1 {
public static void main(String[] args) throws IOException {
/*
* 1.因为BufferedWriter只能提高效率,不能进行写入操作
* 因此创建文件写入流对象,并且要和被写入数据的文件进行关联
*/
FileWriter fr = new FileWriter("F:\\Demo1.txt");
/*
* 2.为了提高写入效率,使用缓冲写入流
* 把需要提高效率的字符输出流对象作为参数传递给BufferedWriter的构造方法
*/
BufferedWriter bw = new BufferedWriter(fr);
//3.使用BufferedWriter对象实现写入数据
for(int i = 1;i<=3;i++){
bw.write(i+":"+"简书");
bw.newLine();//可跨平台显示的换行
//bw.flush();
/*
* 为了更进一步提高效率
* 不建议在此时使用flush()方法刷新
* 可在最后关闭程序时统一刷新写入
*/
}
//4.关闭流
bw.close();//关闭缓冲流相当于关闭了原本的字符流
}
}
3、使用缓冲输入流实现对文件的读取
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class Demo2 {
public static void main(String[] args) throws IOException {
/*
* 1.因为BufferedReader只能提高效率,不能进行读取操作
* 因此创建文件读取流对象,并且要和被读取数据的文件进行关联
*/
FileReader fr = new FileReader("F:\\Demo1.txt");
/*
* 2.为了提高读取效率,使用缓冲读取流
* 把需要提高效率的字符输入流对象作为参数传递给BufferedReader的构造方法
*/
BufferedReader br = new BufferedReader(fr);
/*
* 3.使用BufferedReader对象实现读取数据
* BufferedReader类中有一个每次读取一个文本行的方法readLine()
*/
String line = null;
while((line=br.readLine())!=null){//返回包含该行内容的字符串,不包括最后的换行符
System.out.println(line);
}
//4.关闭流
br.close();
}
}
4、使用缓冲流实现复制文件
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class Demo3 {
public static void main(String[] args) {
/*
* 创建局部变量保证br、br的作用域为整个方法
* 同时为了防止其他异常
* 给引用变量bw、br赋一个初始值null
*/
BufferedReader br = null;
BufferedWriter bw = null;
//使用try块包裹代码,用catch块捕获IO异常
try {
br = new BufferedReader(new FileReader("E:\\Demo1.java"));
bw = new BufferedWriter(new FileWriter("F:\\Demo1_Copy.java"));
//将字符读入数组
String line = null;
while((line = br.readLine())!=null){
bw.write(line);
bw.newLine();//写入换行
}
} catch (Exception e) {
e.printStackTrace();
}
finally{
/*
* close()方法是一定要执行的
* 因此放入finally块中
* 同时该方法要求处理异常
* 因此需要再用try_catch操作
*/
try{
/*
* 如果路径错误,例如 new FileWriter("Z:\\Demo1.java");
* 将导致FileWriter对象创建失败,从而导致BufferedWriter对象创建失败
* 致使finally块的close()方法中的bw不存在,变为null.close();
* 从而引发NullPointException异常,因此要加入if(bw!= null)的判断
*/
if(bw!= null){
bw.close();
}
}catch(IOException e){
e.printStackTrace();
}
try{
if(br!= null){
br.close();
}
}catch(IOException e){
e.printStackTrace();
}
}
}
}
5、缓冲流实现原理
此部分为扩展内容,仅供了解
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
/**
* 模拟BufferedReader,自定义一个类MyBufferedReader,思路如下:
* 1.需要一个真正具备读功能的流对象,所以MyBufferedReader需要定义一个Reader类型的成员
* 2.需要提供一个缓冲区来提高效率,所以需要定义一个数组充当缓冲区
* 3.操作数组需要下标,所以需要定义一个下标
* 4.统计字符的个数,所以需要定义一个变量
* 5.自定3个功能:读取单个字符,每次读取一行,关闭流
* @param args
*/
class MyBufferedReader{
private Reader r;//具备读功能的成员
private char[] arr = new char[1024];//提高效率的缓冲区
private int index;//下标
private int count;//统计缓冲区中字符个数
public MyBufferedReader(Reader r){
this.r = r;
}
//1.一次读取一个的功能
public int myRead()throws IOException{
if(count==0){//先判断缓冲区中是否有字符
count = r.read(arr);//从文件中读一批数据到缓冲区
index = 0;//下标置为0,从头开始取
}
if(count<0){
return -1;
}
int num = arr[index];//从缓冲区取一个字符
count--;//字符数量减一
index++;//下标加一
return num;
}
/*
* 2.一次读取一行的功能
* 反复调用myRead()方法,不满一行的时候存储数据,满一行的时候返回
*/
public String myReadLine() throws IOException{
StringBuilder sb = new StringBuilder();//实现存储字符
int num;
while((num = myRead())!=-1){
if(num=='\r'){//Windows下换行的转义字符为"\r\n"
continue;//如果是'\r',说明不满一行,继续
}else if(num == '\n'){/如果是'\n',说明满一行
return sb.toString();//输出该行
}else{
sb.append((char)num);//不满一行时存储数据
}
}return null;
}
//3.关闭
public void myClose() throws IOException{
r.close();
}
}
//使用main()方法测试自定义类MyBufferedReader
public class MyBufferedReaderTest {
public static void main(String[] args) throws IOException {
FileReader fr = new FileReader("F:\\Demo1.txt");
MyBufferedReader mbr = new MyBufferedReader(fr);
String line = null;
while((line = mbr.myReadLine())!=null){
System.out.println(line);
}
mbr.myClose();
}
}
6、LineNumberReader
LineNumberReader作为BufferedReader的子类,同样属于装饰类,不仅具有BufferedReader提高效率的功能,还有自己所独有的显示和设置行号的功能。
import java.io.FileReader;
import java.io.IOException;
import java.io.LineNumberReader;
public class lineNumber {
public static void main(String[] args) throws IOException {
FileReader fr = new FileReader("F:\\Demo1.txt");
LineNumberReader lnr = new LineNumberReader(fr);
String line = null;
lnr.setLineNumber(5);//设置5,行号即从6开始
while((line = lnr.readLine())!=null){
System.out.println(lnr.getLineNumber()+":"+line);//读取行号
}
lnr.close();
}
/*
* 6:简书
* 7:简书
* 8:简书
*/
}
7、LineNumberReader实现原理
此部分为扩展内容,仅供了解
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
/**
* 模拟LineNumberReader,自定义一个类MyLineNumberReader,思路如下:
* LineNumberReader在BufferedReader的基础上增加了有关行号的处理方法
* 由此就想到可以继承之前模拟的MyBufferedReader
* 再重写myReadLine()方法
* @param args
*/
class MyLineNumberReader extends MyBufferedReader{//继承MyBufferedReader
private int lineNumber;
public MyLineNumberReader(Reader r){
super(r);
}
public void setLineNumber(int lineNumber){
this.lineNumber = lineNumber;
}
public int getLineNumber(){
return lineNumber;
}
public String myReadLine() throws IOException{//重写一次读一行功能
++lineNumber;
return super.myReadLine();
}
}
//使用main()方法测试自定义类MyBufferedReader
public class MyLineNumberReaderTest {
public static void main(String[] args) throws IOException {
FileReader fr = new FileReader("F:\\Demo1.txt");
MyLineNumberReader mnr = new MyLineNumberReader(fr);
String line = null;
while((line = mnr.myReadLine())!=null){
System.out.println(mnr.getLineNumber()+":"+line);
}
mnr.myClose();
}
}
版权声明:欢迎转载,欢迎扩散,但转载时请标明作者以及原文出处,谢谢合作! ↓↓↓
网友评论