黑马程序员_自定义字符流的缓冲区

--------------Android培训java培训、期待与您交流!--------------

        在我们学IO字符流时,讲到了字符流的缓冲区,它能使读取和写入的速度加快(因为内置缓冲区,不需要来回从内存和目的去取元素,类似于中转站),并且提供了一些符合字符特点且便捷的方法,如newLine和readLine方法,都是原来字符流没有的。现在,便模拟读取流的缓冲区,进行自定义的读和读行方法。
        我们知道BufferedReader不是FileReader下的子类对象。这里用到了装饰设计模式。如果因为只是多增加一个缓冲功能便对FileReader进行继承,继承体系会越来越臃肿,试想,如果只为增加一个功能,便对整个继续体系进行继续继承,那有点太耗资源了。所以,继承也有不灵活的地方。因此,我们只对缓冲功能进行单独的封装,谁要这个功能,便和谁关联,这样不是更灵活么。这便是装饰设计模式的一种例子。
        接下来我们分析下缓冲区的原理。BufferedReader对象在读取数据时是这样的:
BufferedReader br = new BufferedReader(new FileReader(file));
		int ch = 0;
		while ((ch = br.read()) != -1) {
			System.out.println((char)ch);
		}
        FileReader比它读取时多了一个对数组的操作。其实,缓冲区就是定义了一个数组,并对外提供了更多的方法对数组进行访问。而这些方法最终操作的都是数组的角标。即缓冲区每次从源中读取一批数据进数组,然后提供外部对元素的操作动作(都是基于角标的)。如果这批数据被外部对象取完之后,缓冲区便会再次从源中读取一批数据。当源中无数据可取时,便返回-1作为结束标记。
        如图,当每读完一个数据,则角标就移至下一位置。但是,每次取都不一定是满值,也就是缓冲区中的数组未必都能转满,因此,我们需要再定义一个计数器,以统计每次读取的个数,根据计数器来判断是否取完源中的数据。

public class MyBufferedReader {
	FileReader fr;
	//缓冲数组的角标
	private int index;
	//读取到的字符数
	private int count = 0;
	//缓冲数组
	char[] chs = new char[1024];
	
	public MyBufferedReader(FileReader fr) {
		this.fr = fr;
	}
	
	public int myRead() throws IOException{
		//count为0,说明还未开始读或者已经读完一次缓冲区,需要将数组角标重置为0
		if (count == 0) {
			//抓取一堆数据进缓冲区
			count = fr.read(chs);
			index = 0;
		}
		//如果没读到数据,说明源中已无数据可取,返回-1作为结束标记
		if (count < 0) {
			return -1;
		}
		//从缓冲区中读出数据
		char ch = chs[index];
		//每读取一个,角标就 +1,移至下一元素,而元素个数则 -1
		index ++;
		count --;
		return ch;
	}
}
        这样,便完成了read的模拟程序。接下来对readLine方法进行编写。
        有了read的方法之后,readLine的模拟不会很难。引用read方法就有了缓冲区,接下来只要有个容易来装这些读取的数据,到换行标记时,再输出即可。
        于是我们想到用StringBuild进行对元素的暂时存储,当读至换行标记,再进行输出。换行标记是“\r”和“\n”,读到这两个字符我们都不存,读到“\n”时就进行输出。

public String myReadLine() throws IOException{
		//存储元素的“容器”
		StringBuilder sb = new StringBuilder();
		
		int ch;
		while ((ch = myRead()) != -1) {
			//当读取'\r'时,循环进入下一次迭代
			if (ch == '\r') 
				continue;
			//换行标记读完,则把读到的行内容返回
			if (ch == '\n') {
				return sb.toString();
			}
			//存储元素
			sb.append((char)ch);
		}
		
		
		if (sb.length() != 0) {//①
			return sb.toString();
		}
		return null;
	}
        当读至①时,也就是最后一行,如果没有换行标记,也就没有'\r'和'\n',这样便读不到if (ch == '\n')后面的输出语句,那最后一句便不能输出,因此,增加此判断,当最后“容器”还有内容时,就将内容输出。
        最后是关闭流,其底层关闭的就是FileReader,即
public void myClose() throws IOException {
		fr.close();
	}
     以上,便完成了对字符流缓冲区的分析和模拟。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Java,我们可以使用缓冲字符流字符流缓冲区来读取文件。这两种方法都比直接使用字符流要高效得多。 使用缓冲字符流读取文件的步骤如下: 1. 创建FileReader对象,用于读取文件。 2. 创建BufferedReader对象,将FileReader对象作为参数传递给它。 3. 调用BufferedReader对象的readLine()方法读取文件内容。 4. 循环调用readLine()方法,直到返回null,表示文件已读取完毕。 5. 关闭BufferedReader对象和FileReader对象。 示例代码如下: ``` FileReader fr = new FileReader("file.txt"); BufferedReader br = new BufferedReader(fr); String line; while ((line = br.readLine()) != null) { System.out.println(line); } br.close(); fr.close(); ``` 使用字符流缓冲区读取文件的步骤如下: 1. 创建FileReader对象,用于读取文件。 2. 创建char数组,作为字符流缓冲区。 3. 创建int变量,用于记录从文件读取的字符数。 4. 循环读取文件内容,每次读取一定数量的字符缓冲区。 5. 关闭FileReader对象。 示例代码如下: ``` FileReader fr = new FileReader("file.txt"); char[] buffer = new char[1024]; int len; while ((len = fr.read(buffer)) != -1) { System.out.println(new String(buffer, 0, len)); } fr.close(); ``` 注意,在使用字符流缓冲区读取文件时,我们需要使用String类的构造方法将char数组转换成字符串。同时,需要注意读取到的字符数len可能小于缓冲区的大小,因此在构造字符串时需要指定有效字符的长度。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值