黑马程序员技术交流社区

标题: 面试时有个男老师问了我一个关于BufferedReader的问题 [打印本页]

作者: 2666fff    时间: 2015-6-5 19:50
标题: 面试时有个男老师问了我一个关于BufferedReader的问题
本帖最后由 2666fff 于 2015-6-7 13:46 编辑

提高悬赏,来个官方正式点的回答。没人答出为什么我说的不对,我就一直加悬赏。


我的回答是:当BufferedReader在读取文本文件时,会先从文件中读入数据,并置入其所提供的缓冲区,
然后后面的byte[] 数组br.read()方法,会先从缓冲区中进行读取。
然后老师说让我在好好想想,因为当时还专门看过这个,于是我觉得我赵日天不服。


然后我goolge了一下,发现对于这个网络上有两种解释:
1. java.io.BufferedReader和java.io.BufferedWriter类各拥有8192字符的缓冲区。当BufferedReader在读取文本文件时,会先尽量从文件中读入字符数据并置入缓冲区,而之后若使用read()方法,会先从缓冲区中进行读取。如果缓冲区数据不足,才会再从文件中读取,使用BufferedWriter时,写入的数据并不会先输出到目的地,而是先存储至缓冲区中。如果缓冲区中的数据满了,才会一次对目的地进行写出。

来源
http://xyiyy.iteye.com/blog/361476
这个基本跟我说的一样。


第二种:
这么说吧,这个类就是一个包装类,它可以包装字符流,将字符流放入缓存里,先把字符读到缓存里,到缓存满了或者你flush的时候,再读入内存,就是为了提供读的效率而设计的。

来源:

http://zhidao.baidu.com/link?url=53hXzhh70y4Dny5w9faS2pIPdrLc1vZnccZNEoLtzKi-vCa7KnzNOZMH-ZPBUPvIf0wBo0WrIl9YPsvkHaSBJa
这个没提到之后从缓冲区再怎么read,所以我就不是很明白了。

再查看java 自带API:
java.io
Class BufferedReader
public class BufferedReader
extends Reader
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.

api中也只说了,它提供足够大的buffer,用来buffering characters, 可以调高读取效率,但是没有说为何提高,如何提高,
那么问题就来了:
挖掘机技术到底哪家强?

回答的请专业点,一两行就觉得能完事的就不要来了,回答的好有加分哦。
最好当时面试的那个男老师能来帮我解答一下。

作者: as604049322    时间: 2015-6-5 19:51
本帖最后由 as604049322 于 2015-6-8 11:13 编辑

我的回答是:当BufferedReader在读取文本文件时,会先从文件中读入数据,并置入其所提供的缓冲区,
然后后面的char[] 数组br.read()方法,会先从缓冲区中进行读取。
--------------------------------------------------------------------------------------
楼主不说清楚老师问了什么,,还我们得分析加猜测老师问了啥,,想半天。。
我猜老师应该是问:
-------------------------------------------------------------------------
BufferedReade高效的原理是什么???
任何流底层从磁盘读取数据都是一次读一个字节,如果读一个字节之后马上要写数据这样就需要移动磁头,而移动磁头的时间远远高于读取的时间。而有时我们一次把所有内容读入到内存,空间又不够,,于是设计了BufferedReader等缓冲区的类,其实所谓的缓冲区底层就是一个数组,为了减少频繁移动磁头带来的时间消耗,BufferedReader在调用read方法读取数据时,,会首先检查数组里面是否存在已经读取的数据,若不存在则从底层流读取数组长度的字符保存起来。若存在则直接返回数组中的字符。这个问题我感觉我用文字很难说清楚,,所以只说了最简单的情况。
------------------------------------------------------------------------------------------------------
再说说你的回答,,,我先跟你改一改
当BufferedReader在读取文本文件时,会先判断缓冲区是否存在数据,若不存在则会从文件中读入数据,并保存到char[]数组(缓冲区)中,以前不断调用read()方法读取字符时,都会不断的判断,并调整指针位置,直到缓冲区为空时,又会从文件读取数据到缓冲区。


就算你心里时这么想的,,但回答的太笼统,,看不出这层意思。

如果你觉得你表达的够清楚,,真的把缓冲区搞懂了,,你就在老师面前写一个缓冲区出来,,说实话我的表达也还是不太清楚,,如果老师不认同我就会在他面前写个缓冲区出来,,证明自己的实力。

凡事想想自己的问题


作者: Enhon1992    时间: 2015-6-5 20:24
BufferedReader 是字符输入流缓冲区,这个类是采用装饰设计模式来设计的,在创建这个类的对象的时候,需要接收一个字符输入流对象,这样可以提高字符输入流读取数据的效率;
调用这个类的read方法 实际上是调用的创建该类对象的时候传进来的字符输入流的read方法,然后用read从源中读取数据 存放到这个类封装的字节数组,当调用该类的readerLine()实际上是从字节数组中读取的,没有直接从源中读取数据 而是从内存中读取数据 所以效率很高;
作者: 开弓没有回头箭    时间: 2015-6-6 09:32
本帖最后由 开弓没有回头箭 于 2015-6-6 09:33 编辑

bufferedReader要与bufferdWriter配合使用才有意义。如果只是读出来,打印到控制台,bufferedReader和Reader没有太大差别。
bufferedReader的出现是为了避免这样的情况:Reader是读取一个字符,Writer写一个字符,没有bufferedReader的情况下,Reader一个字符就要Writer一个,对硬盘来讲,磁头读取一个字符,必须去找磁盘上到写的地方,写一个字符。如果是长的字符串,磁头就必须在读的区域和写的区域来回移动,因此效率的。bufferedReader就是把要读取的字符串先读完,在一次性写,避免磁头来回移动,以此来提高读写效率。也就是说可以自己定义一段缓存空间来保存Reader出来的数据,效果和bufferedReader一样
所以不涉及到硬盘这类外存的读写,bufferedReader对于提高效率没有什么效果,但因其提供的方便的读取方法,比如readLine方法,所以一般会用bufferedReader

作者: 志行    时间: 2015-6-6 11:26
问的是什么问题啊?
作者: huadengaiyue    时间: 2015-6-7 02:10
还牛逼呀

作者: lijiansheng    时间: 2015-6-7 10:14
忘了什么区别了
作者: xtf    时间: 2015-6-7 11:32
Enhon1992 发表于 2015-6-5 20:24
BufferedReader 是字符输入流缓冲区,这个类是采用装饰设计模式来设计的,在创建这个类的对象的时候,需要 ...

认真学习下!
作者: Enhon1992    时间: 2015-6-7 11:37
xtf 发表于 2015-6-7 11:32
认真学习下!

我说错了吗?

作者: Enhon1992    时间: 2015-6-7 11:44
xtf 发表于 2015-6-7 11:32
认真学习下!

我说错了吗?

作者: 2666fff    时间: 2015-6-7 13:44
Enhon1992 发表于 2015-6-5 20:24
BufferedReader 是字符输入流缓冲区,这个类是采用装饰设计模式来设计的,在创建这个类的对象的时候,需要 ...

我跟你解释的差不多吧:
然后用read从源中读取数据 存放到这个类封装的字节数组,没有直接从源中读取数据 而是从内存中读取数据 所以效率很高;

可是老师为什么让我好好想想? 这论坛有没有官方的人来回答这个问题?

作者: storer    时间: 2015-6-7 22:44
说还真是不好说呀。
作者: 君子无醉    时间: 2015-6-8 01:01
我觉得 老师让你再想想的原因,可能是你把char[]数组说成了byte[]数组。因为包装的是字符流。。
作者: 十里坡    时间: 2015-6-8 13:27
as604049322 发表于 2015-6-7 16:28
我的回答是:当BufferedReader在读取文本文件时,会先从文件中读入数据,并置入其所提供的缓冲区,
然后后 ...

学习了!!!赞
作者: hzw@ql    时间: 2015-6-8 18:36
流的一章,学的也很混乱
作者: 壹颗心只属于你    时间: 2015-6-8 20:19
来学习:victory:
作者: l李伟    时间: 2015-6-8 21:57
我表示路过,没有学到那步
作者: 小田    时间: 2015-6-8 23:53
本帖最后由 小田 于 2015-6-8 23:57 编辑

“当BufferedReader在读取文本文件时,会先从文件中读入数据,并置入其所提供的缓冲区,”这句话没问题,我看了BufferedReader的源码,他自身 有一个自带的私有化的字符数组,

L`29MLFMSMKSQS}JH$1F4BE.png (12.75 KB, 下载次数: 178)

这个是BbufferedReader的源码的一部分

这个是BbufferedReader的源码的一部分

作者: lucien_he    时间: 2015-6-9 10:16
感觉自己学的好不扎实
作者: 路途遥远    时间: 2015-6-9 11:35
探究的很深啊,要是我,我跟楼主回答的也一样
作者: 路途遥远    时间: 2015-6-9 11:36
as604049322 发表于 2015-6-7 16:28
我的回答是:当BufferedReader在读取文本文件时,会先从文件中读入数据,并置入其所提供的缓冲区,
然后后 ...

:o 厉害,赞!!!
作者: 人在旅途~东营    时间: 2015-6-12 22:23
搞的好乱啊,都很有道理的样子,但我觉得不需要纠结这个啊,讲明白原理就行了,没啥服气不服气的
作者: qq496099229    时间: 2015-6-12 22:27
其实要回答这个问题,直接拿MyBufferedReader的设计思路去问答就好了。要是问,为什么高效,就说利用缓存减少了IO切换
作者: 精灵来了    时间: 2015-6-13 01:00
你对比一下API中的BufferedReader和Reader就会发现,他们唯一的区别是BufferedReader提供了ReadLine()允许一行一行的读的增强方法,提高每次读取的效率,老师主要是想让你说出ReadLine()是BufferedReader存在的意义
作者: 滑板鞋    时间: 2015-6-13 08:49
学习了,赞赞赞.
作者: liu100chao    时间: 2015-6-16 20:33
这还真是 锱铢必较啊!
作者: wgy    时间: 2015-6-17 08:04
从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。

可以指定缓冲区的大小,或者可使用默认的大小。大多数情况下,默认值就足够大了。

通常,Reader 所作的每个读取请求都会导致对底层字符或字节流进行相应的读取请求。因此,建议用 BufferedReader 包装所有其 read() 操作可能开销很高的 Reader(如 FileReader 和 InputStreamReader)。
例如,
BufferedReader in
   = new BufferedReader(new FileReader("foo.in"));
将缓冲指定文件的输入。如果没有缓冲,则每次调用 read() 或 readLine() 都会导致从文件中读取字节,并将其转换为字符后返回,而这是极其低效的。
通过用合适的 BufferedReader 替代每个 DataInputStream,可以对将 DataInputStream 用于文字输入的程序进行本地化。
  其中构造方法主要有两个:
   BufferedReader(Reader in),这是指创建一个使用默认大小输入缓冲区的缓冲字符输入流。
   BufferedReader(Reader in, int sz),z这是指创建一个使用指定大小输入缓冲区的缓冲字符输入流。
   大概就是这样吧。


作者: jake_liu    时间: 2015-6-19 13:40
君子无醉 发表于 2015-6-8 01:01
我觉得 老师让你再想想的原因,可能是你把char[]数组说成了byte[]数组。因为包装的是字符流。。 ...

说到点子上去了
作者: 342508558    时间: 2015-6-20 23:14
java核心技术卷二13页:“在javaSE5.0之前,处理文本输入的唯一方式就是通过BufferReader类,它拥有一个readLine方法可以使我们读入一行文本。你需要将带缓冲区的读入器与输入源组合起来

oracle api :Reads text from a character-input stream, buffering characters so as to provide for the efficient reading of characters, arrays, and lines.***Without buffering, each invocation of read() or readLine() could cause bytes to be read from the file, converted into characters, and then returned, which can be very inefficient.

所以BufferReader是不能直接从文件读数据的,只能从字符流里面读数的。
作者: j420984    时间: 2015-6-23 09:54
问题都没看到!
作者: hakey    时间: 2015-7-3 16:27
采纳的回答,果然很给力,学到了
作者: aurora_bessie    时间: 2015-7-20 10:12
来学习~




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2