黑马程序员技术交流社区

标题: write(buffer, 0, len)一定要传入len吗? [打印本页]

作者: 严明    时间: 2012-6-26 18:31
标题: write(buffer, 0, len)一定要传入len吗?
本帖最后由 严明 于 2012-6-27 00:00 编辑

在毕老师复制mp3文件的视频里,有这么一段代码,声明mp3文件比1024大

FileInputStream fis = newFileInputStream("a.mp3");

       FileOutputStream fos= new FileOutputStream("copy.mp3");
        byte[]buffer = new byte[1024];
        int len;
        while ((len= fis.read(buffer)) != -1)
                fos.write(buffer, 0,len);

               
        fis.close();
        fos.close();
我将红色部分改成:
fos.write(buffer);   这样也能复制成功
那么write()的时候为什么传入数组的长度呢? 视频中好像是这样说的:
最后一次将字节装入字节数组中, 但是最后一次读取的字节总数 并没有1024 ,
所以最后一次读取的数据会覆盖 倒数第二次装在数组中的数据, 但是它无法全部覆盖,那么 就会覆盖数组的前半部分了 数组的后半部分仍然是倒数第二次的数据.

我用fos.write(buffer) 这样是将最后一次数组里面的全部数据(包括最后一此存在数组里面前半部分的 和 倒数第二次保留在数组后半部分的)都写入文件copy.mp3
按理说这种方法复制出来的文件字节总数一定会比原文件大, 但是结果是跟原文件是一样大的,why?




作者: 李伟    时间: 2012-6-26 19:06
应该是你复制的文件小于1024字节或者是你复制的文件正好是1024字节的整数倍。
作者: 邱国    时间: 2012-6-26 19:22
本帖最后由 邱国 于 2012-6-26 19:30 编辑

一个个回答:
仔细看API文档,下面是对write(byte[] b)的说明:
write
public void write(byte[] b)
           throws IOException
将 b.length 个字节从指定的 byte 数组写入此输出流。write(b) 的常规协定是:应该与调用 write(b, 0, b.length) 的效果完全相同

public void write(byte[] b,
                  int off,
                  int len)
           throws IOException将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此输出流。write(b, off, len) 的常规协定是:将数组 b 中的某些字节按顺序写入输出流;元素 b[off] 是此操作写入的第一个字节,b[off+len-1] 是此操作写入的最后一个字节。

这就解释了你的问题,其实你用wtite(buffer)和write(buffer, 0,len);都是一样的,之所以建议用后面那个write方法,其实是避免如果文件大小非常少的话,用后面的方法可以理论上避免了传入   把数组后面没用到的内存空间。     只传入0到length的部分,没传入数组后面没用的部分





作者: 赵庆礼    时间: 2012-6-26 19:29
大小是不一样的,fos.write(buf)比原文件大

左图是fos.write(buf),右图为fos.write(buf,0,len)复制文件,和原文件大小一样
作者: 王莹    时间: 2012-6-26 19:41
本帖最后由 王莹 于 2012-6-26 19:43 编辑

调用的read方法,有两种形式,一种是read(byte [] b),一种是read(byte[] b,int off,int len),对应到你的程序中就是read(buffer)和read(buffer,0,len).
你拷贝的MP3文件应该是要大于定义的数组buf的大小1k的,所以取到最后应该取到最后一次,实际返回的长度小于或者等于1024个字节,这时如果使用read(buf,0,len)会返回恰好的长度,而你使用read(buf),返回的长度肯定是1024,如果你拷贝的文件不是正好是1024的整数倍就肯定会多返回一些字节值的。我用这两种方式都运行了一遍。在文件属性值查得的结果如下:

原文件大小:


read(buf)方式:


read(buf,0,len)方式:


如果你说你所运行的两个方式的程序结果都是一样的,那恭喜你,你的那个MP3文件就正好是1024字节的整数倍了,真神奇~~~

作者: 严明    时间: 2012-6-27 00:03
王莹 发表于 2012-6-26 19:41
调用的read方法,有两种形式,一种是read(byte [] b),一种是read(byte[] b,int off,int len),对应到你的程 ...

真的,我换一个文件试了试,果然,像你说的一样会比原文件大一点点!
作者: 王涛    时间: 2012-6-27 02:09
其实用这个fos.write(buffer, 0,len);主要还是因为你的这个byte[]buffer = new byte[1024];
开辟的这个byte数组的大小事1024,但是实际上很多文件的最后需要装入一个字节数组的字节不会那么正好是1024,也就是说存在了空白的空间,再将这个数组写入时也罢这些无用的空间写入了
这样的操作坑定不合理的,所以定义了一个len变量,记录(len= fis.read(buffer),她的返回值表明了向数组中写入了多少个数据
这样就没有多余的空间呗写入了。




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