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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 up.yfei 于 2013-5-26 20:55 编辑

如题,看了视频,还是不明白 缓冲区是干嘛的

缓冲区的意思是不是说,读一个写一个太麻烦,然后定义个缓冲区,一次读很多,然后再一次写很多?

那和下面代码中的 byte[] buf = new byte[1024]  不就一样了?
  1. fos = new FileOutputStream("e:\\1.jpg");//输出目标
  2.                         fis = new FileInputStream("e:\\2.jpg");//读取文件的目标

  3.                         byte[] buf = new byte[1024];

  4.                         int len = 0;
  5.                         while((len=fis.read(buf))!=-1)
  6.                         {
  7.                                 fos.write(buf,0,len);
  8.                         }
复制代码
而且还有个疑问,就是说,缓冲区的话 len=fis.read(buf)  len 怎么会返回-1? len返回的不应该是存入数组中元素的个数么?

比如说有个文件   1034字节, 第一次 读了 1024 存进 buf 数组 ,然后剩下10字节,下次读,那么下次不就应该返回10么,怎么会返回-1?


缓冲已经卡我好几天了,看好几遍了,还是不知道干啥的...
先感谢各位了!!!

评分

参与人数 1技术分 +1 收起 理由
Sword + 1

查看全部评分

7 个回复

正序浏览
陈雨 中级黑马 2013-5-26 20:21:01
8#
up.yfei 发表于 2013-5-26 14:23
我有点迷惑的是
fos = new FileOutputStream("e:\\1.jpg");//输出目标
                        fis = n ...

其实也没多少的区别,数组可以看成是缓冲区,只不过BufferReader等缓冲区功能比较多,他们只不过是将一些方法封装了,更方便操作,有回车标记,读一行等方法.

点评

我大概明白了,太感谢了,3Q  发表于 2013-5-26 20:24
回复 使用道具 举报
up.yfei 发表于 2013-5-26 14:23
我有点迷惑的是
fos = new FileOutputStream("e:\\1.jpg");//输出目标
                        fis = n ...

   你那个数组其实就起到了一个简单的缓冲作用,先将数据读出来存到数组中,然后在将数组中的数组写入,
不过缓冲区的数组的大小你一定要定义好。   不知道你看源码没有 看里面的缓冲区 看他的定义 他的写读的方法也是直接将InputStream穿进去 然后里面有确定数组长度的,
   public synchronized int read() throws IOException {
        if (pos >= count) {
            fill();
            if (pos >= count)
                return -1;
        }
        return getBufIfOpen()[pos++] & 0xff;
    }这个是他的读的方法 可是你看fill();方法
// 在这个方法中来确定缓冲区的长度  我看的也不是很懂  只能看懂个大概 你在看前面的几个方法  有好几个都是贯穿着,他其中获得数组
private void fill() throws IOException {
        byte[] buffer = getBufIfOpen();   //这里是从上文的getBufIfOpen();   这个方法中获取数组  下面的都是英文了  你慢慢读  想要深入了解 就去读源码 最好
        if (markpos < 0)
            pos = 0;            /* no mark: throw away the buffer */
        else if (pos >= buffer.length)  /* no room left in buffer */
            if (markpos > 0) {  /* can throw away early part of the buffer */
                int sz = pos - markpos;
                System.arraycopy(buffer, markpos, buffer, 0, sz);
                pos = sz;
                markpos = 0;
            } else if (buffer.length >= marklimit) {
                markpos = -1;   /* buffer got too big, invalidate mark */
                pos = 0;        /* drop buffer contents */
            } else {            /* grow buffer */
                int nsz = pos * 2;
                if (nsz > marklimit)
                    nsz = marklimit;
                byte nbuf[] = new byte[nsz];
                System.arraycopy(buffer, 0, nbuf, 0, pos);
                if (!bufUpdater.compareAndSet(this, buffer, nbuf)) {
                    // Can't replace buf if there was an async close.
                    // Note: This would need to be changed if fill()
                    // is ever made accessible to multiple threads.
                    // But for now, the only way CAS can fail is via close.
                    // assert buf == null;
                    throw new IOException("Stream closed");
                }
                buffer = nbuf;
            }
        count = pos;
        int n = getInIfOpen().read(buffer, pos, buffer.length - pos);
        if (n > 0)
            count = n + pos;
    }   

点评

我大概明白了,太感谢了,3Q  发表于 2013-5-26 20:24

评分

参与人数 1技术分 +1 收起 理由
Sword + 1

查看全部评分

回复 使用道具 举报
花开花落总相似 发表于 2013-5-25 19:05
是的  缓冲区就是一次读好多个 然后在一起存 你理解的没错啊,
你说的为什么会返回-1   读到结尾了 然后 ...

我有点迷惑的是
fos = new FileOutputStream("e:\\1.jpg");//输出目标
                        fis = new FileInputStream("e:\\2.jpg");//读取文件的目标

                        byte[] buf = new byte[1024];

                        int len = 0;
                        while((len=fis.read(buf))!=-1)
                        {
                                fos.write(buf,0,len);
                        }

他和缓冲区有区别么?
缓冲区是读一部分,然后先存起来,然后再写,想上面的代码,也不就是先读一部分,然后再写?

评分

参与人数 1技术分 +1 收起 理由
Sword + 1

查看全部评分

回复 使用道具 举报
陈雨 发表于 2013-5-25 20:41
看你这么纠结,忍不住要来拯救你了(在网吧上网,知识记得不是很细节了,又没带笔记于是找到了视频再看了一 ...

我有点迷惑的是
fos = new FileOutputStream("e:\\1.jpg");//输出目标
                        fis = new FileInputStream("e:\\2.jpg");//读取文件的目标

                        byte[] buf = new byte[1024];

                        int len = 0;
                        while((len=fis.read(buf))!=-1)
                        {
                                fos.write(buf,0,len);
                        }

他和缓冲区有区别么?
缓冲区是读一部分,然后先存起来,然后再写,想上面的代码,也不就是先读一部分,然后再写?
回复 使用道具 举报
本帖最后由 陈雨 于 2013-5-25 20:47 编辑

看你这么纠结,忍不住要来拯救你了(在网吧上网,知识记得不是很细节了,又没带笔记于是找到了视频再看了一下)
    老毕的视频里面其实说的很详细了,可能楼主跳跃式看的。见视频18天-10-IO流11分20秒和18天-11-IO流5分40秒位置
    比如一组数据abcde存在硬盘里,当硬盘读取数据时,盘片会扫描上面的数据abcde,应该是一个一个读的,如果有缓存区,其实缓冲区就是先存在内存里面,(缩短了硬盘来回读写的距离,先存入缓冲区然后一次性写到目的地)它会将硬盘读取的数据先存入缓冲区,每段数据在硬盘上存储时都有结束标记,当硬盘扫描到结束标记时,java判断会这个标识,然后返回-1.
    read调用时有自动读取下一个的功能,当你读完最后10个时,是返回10,但是再往下读就读要硬盘里的结束标记了,-1了.这时循环结束。   
    另read() API里面备注的很清楚了,返回:作为整数的字符,范围在0到65535之间,如果已到达流的末尾,则返回-1。
   还纠结吗?其实很多东西都定义好了,我们了解它的功能就行了,至于底层怎么实现的,那是c语言和C++工程师们考虑的问题了。
    求版主赐予最后一分。

评分

参与人数 1技术分 +1 收起 理由
Sword + 1

查看全部评分

回复 使用道具 举报
先know how,再know why  多敲敲代码就了解了。。。别人说的再好也不如自己去理解的好,别急
回复 使用道具 举报
本帖最后由 花开花落总相似 于 2013-5-25 19:10 编辑

  是的  缓冲区就是一次读好多个 然后在一起存 你理解的没错啊,
你说的为什么会返回-1   读到结尾了 然后返回一个值表示说 我这一行已经读完了  要换行。
     毕老师不是教过模仿写一个缓冲区吗。  如果在想深究  那就去查看源码啊  JDK下面那个src的压缩包 里面的都是源码
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马