A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 观决 中级黑马   /  2014-5-19 11:54  /  6791 人查看  /  8 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 观决 于 2014-5-19 19:26 编辑

我看源码里面里面没得定义 是在Writer.java里面看的   如下这个貌似不是默认缓冲的大小然后我又看了 Reader.java的源码 里面倒是定义了   然后自己测试了一下  发现部不刷新 一次最多存入8k  实验证明是8k但是源码里面没写啊 怎么是8K的   我想问源码里面没得怎么确定8k的默认缓冲的
  1. public class IODemo01
  2. {
  3.         public static void main(String [] args) throws Exception{
  4.                 byte [] arrs=new byte[10*1024];
  5.                 FileWriter out=new FileWriter("arrs.txt");
  6.             
  7.                 for(int i=0;i<arrs.length;i++){
  8.                      
  9.                 arrs[i]=(byte)2;
  10.                 }
  11.         //        System.out.println(arrsStr);
  12.         String Str=new String(arrs);
  13.                 out.write(Str);
  14.                 //out.close();
  15.         }
  16. }
复制代码

Writer.jpg (89.18 KB, 下载次数: 17)

Writer.jpg

Reader.jpg (65.64 KB, 下载次数: 13)

Reader.jpg

QQ截图20140519115353.jpg (23.55 KB, 下载次数: 12)

QQ截图20140519115353.jpg

评分

参与人数 1技术分 +1 收起 理由
轻语。 + 1

查看全部评分

8 个回复

倒序浏览
我记得毕老师的视频讲过writer中使用的是字节流的缓冲区。

public abstract class OutputStream implements Closeable, Flushable {
    /**
     * Writes the specified byte to this output stream. The general
     * contract for <code>write</code> is that one byte is written
     * to the output stream. The byte to be written is the eight
我也没看太明白,应该是这样。。。
回复 使用道具 举报
学习咯。。。。。。。。。。。。。。。
回复 使用道具 举报
zhrnghgwsws 发表于 2014-5-19 12:55
我记得毕老师的视频讲过writer中使用的是字节流的缓冲区。

public abstract class OutputStream implement ...

    Writer.java中的这个方法的源码就是这样  他根本没做什么处理  
    public void write(String str) throws IOException {
        write(str, 0, str.length());
    }

我看了这几个相关的 也都没找到什么定义默认的缓冲区的大小相关配置    那个Reader.java里面倒是配置了默认缓冲区的大小为8192   8K  我不理解的是Reader.java配置了为什么Writer.java里面没配置  而且实验证明Writer默认也是8K    我在看看源码吧
回复 使用道具 举报
我拿你的例子做了实验,你把字节数组的大小设置成20k试试,那么在不刷新的前提下写入的大小是16K,设置成30k,写入的大小就是24k,这说明在不刷新的情况下写入的可能就是8的倍数,多余大小的数据在不刷新或不关闭流的情况下,是写入8的倍数,剩余不足8k就还在缓冲区。其实我可以不可以这样来理解,你定义了一个20k的数组,直接用write写,但是在写入之前,是不是也是Reader或者是其他的输出流来读取这个数组的,所以缓冲就是8k了。

评分

参与人数 1技术分 +1 收起 理由
轻语。 + 1

查看全部评分

回复 使用道具 举报

     
     BufferedWriter和BufferedReader是给流创建一个缓冲区,使在流读取或写入时先将流存入缓存,然后对流进行操作,提高效率,BufferedReader比较好理解,我们创建好一个FileReader对象后,用BufferedReader进行包装,然后会将文件预先读取到缓冲中,我们可以直接对缓冲进行操作,而不用读一次去硬盘上取一次数据。但在思考BufferedWriter时,我遇到了一些问题。
     假如BufferedWriter是创建一个缓冲的话,那么FileWriter就应该不会含有缓冲区,每次调用FileWriter对象的Write方法就应该是直接写入到磁盘中,但我们直接调用FileWriter对象Write方法写入少量数据而不调用flush方法和close方法时,可以清楚的看见在我们指定的目录下生成了我们要创建的文件,而文件内容为空。既然文件为空,那么就不是直接对磁盘操作,所以我们可以断定写入的内容保存在内存中,内部肯定运用了缓冲机制。这样就有两种可能:1.Java提供了缓冲机制;2.windows提供了缓冲机制(我用的windows平台)。
     接下来,我用WIN32汇编编写了一个调用windowsAPI实现写文件的小程序,程序的功能只是调用CreateFile打开一个文件,然后调用WriteFile写入10个字符,最后是一个无限空循环。运行程序后,在目录上生成了文件,打开文件后,文件中保存了我要写入的10个字符,所以不是windows提供的缓冲机制。
    既然是Java提供了缓冲机制,那么这个缓冲区一定有最大的限制,我编写了一个程序进行测试。
    public class Liu {

         public static void main(String[] args){
             FileWriter fw=null;
            //FileReader fr;
            try{
                   fw=new FileWriter("D://a.txt");
                   for(int i=0;i<100000;i++)
                        fw.write('a');
                }
            catch(IOException e){   
            }
       }
   }

运行程序后,文件创建了,而且文件中有了内容,我们可以断定,在这个缓冲区满了之后。不用调用flush方法,java会自动将保存在缓冲区的内容写入到磁盘上。
之后又编了一个取得字符个数程序:

  写入10万个a, 最后保存起来的是98304个a, 在反复多次试验中,我发现了当我写入8193个字符时,文件中最后会保存8192个字符,而当写入的字符小于8192时,文件中不会有任何东西。所以java中提供的缓冲区大小应该为8KB。
   最后我写了一个用BufferedWriter包装了的FileWriter写入内容的程序:
            
    结果跟不用BufferedWriter包装的程序结果差不多:当写入的字符小于16K时,文件中不会有任何东西。而写入大于16k+1的字符时,保存的字符数为 8192,在此基础上输入的字符数每加8K,实际写入的数据也同样加8k,所以我们可以认为BufferedWriter中缓存大小为16K,而且每当缓冲区满而没有进行刷新操作时,java会自动写入磁盘8K数据。
    经过实验我们可以看出:无论使不使用BufferedWriter,当向文件中写入数据时,数据流始终先保存到一段缓冲区中,当写入的数据流大于8KB(使用BufferedWriter包装后是16K)而没有进行刷新流操作时,JAVA会自动刷新流,将流写入到文件中。

评分

参与人数 1技术分 +1 收起 理由
轻语。 + 1

查看全部评分

回复 使用道具 举报
观决 中级黑马 2014-5-19 19:22:58
7#
本帖最后由 观决 于 2014-5-19 19:31 编辑
zhrnghgwsws 发表于 2014-5-19 14:39
BufferedWriter和BufferedReader是给流创建一个缓冲区,使在流读取或写入时先将流存入缓存,然 ...

刚才上课回来 我就按照源码里面的最开始的方法一个一个的推   终于找到那个8192了  坑爹啊....

Writer.java中的write()
public void write(char cbuf[]) throws IOException {
        write(cbuf, 0, cbuf.length);
    }

这里去找write(cbuf, 0, cbuf.length);
public void write(String str, int off, int len) throws IOException {
        synchronized (lock) {
            char cbuf[];
            if (len <= writeBufferSize) {
                if (writeBuffer == null) {
                    writeBuffer = new char[writeBufferSize];
                }
                cbuf = writeBuffer;
            } else {        // Don't permanently allocate very large buffers.
                cbuf = new char[len];
            }
            str.getChars(off, (off + len), cbuf, 0);
            write(cbuf, 0, len);
        }
    }

这里就要找到write(cbuf, 0, len);这里发现是一个抽象类
  abstract public void write(char cbuf[], int off, int len) throws IOException;

这里就找到了子类OutputStreamWriter 里面的方法
public void write(char cbuf[], int off, int len) throws IOException {
        se.write(cbuf, off, len);
    }

这里的se 是一个private final StreamEncoder se;这个类  
然后我看了上面的导入
import sun.nio.cs.StreamEncoder;
这个包里面  我就在src下面找  (根本就没有  我就凌乱了)
然后  我就百度了这个StreamEncoder
幸好百度有链接在这里
http://www.docjar.com/html/api/sun/nio/cs/StreamEncoder.java.html
下面是实现的代码
private static final int DEFAULT_BYTE_BUFFER_SIZE = 8192; 默认的大小
public void write(char cbuf[], int off, int len) throws IOException {
  synchronized (lock) {
         ensureOpen();
            if ((off < 0) || (off > cbuf.length) || (len < 0) ||
                ((off + len) > cbuf.length) || ((off + len) < 0)) {
            throw new IndexOutOfBoundsException();
        } else if (len == 0) {
                return;
       }
           implWrite(cbuf, off, len);   下面又是这个方法
      }
    }


   void implWrite(char cbuf[], int off, int len)  263           throws IOException
  264       {
  265           CharBuffer cb = CharBuffer.wrap(cbuf, off, len);
  266   
  267           if (haveLeftoverChar)
  268           flushLeftoverChar(cb, false);
  269   
  270           while (cb.hasRemaining()) {
  271           CoderResult cr = encoder.encode(cb, bb, false);
  272           if (cr.isUnderflow()) {
  273              assert (cb.remaining() <= 1) : cb.remaining();
  274              if (cb.remaining() == 1) {
  275                   haveLeftoverChar = true;
  276                   leftoverChar = cb.get();
  277               }
  278               break;
  279           }
  280           if (cr.isOverflow()) {
  281               assert bb.position() > 0;
  282               writeBytes();
  283               continue;
  284           }
  285           cr.throwException();
  286           }
  287       }

然后又是一些方法的调用   void implWrite(char cbuf[], int off, int len)
这里后面就一直调用吧 <这里代码基本开始看不懂了>  不过起码找到了这个8192的默认值  
回复 使用道具 举报
受教了啊~~
回复 使用道具 举报
思维 高级黑马 2014-7-22 11:01:14
9#
还真没想过这个问题!:o
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马