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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 郑传庆 于 2012-6-8 21:51 编辑

用FileInputStream在读取文件的时候,定义缓冲区的大小用下面哪个比较好?它们在什么情况下使用比较合适?
byte[] buff = new byte[input.availabe()]和byte[] buff = new byte[1024]

评分

参与人数 1技术分 +1 收起 理由
黄奕豪 + 1 赞一个!

查看全部评分

6 个回复

倒序浏览
availabe()在有些 InputStream 的实现将返回流中的字节总数,但也有很多实现不会这样做。试图使用此方法的返回值分配缓冲区,以保存此流所有数据的做法是不正确的。
也就是说,因为网络传输的非实时性,在你的程序去检查available的时候,实际上另一端可能还没有发送数据,或对方网络拥挤,要发给你的数据包还在队列中。所以你调用 available时有可能 会返回0。

建议你还是用1024吧。

评分

参与人数 1技术分 +1 收起 理由
黄奕豪 + 1 赞一个!

查看全部评分

回复 使用道具 举报
byte[] buff = new byte[input.availabe()]是根据读取流的剩余字节变化长度的,一般读取内容少的文件的时候用会效率高,因为刚刚好一次就把源文件读取到了缓冲中,但是在内容量大的文件读取的时候用这种方法,有可能会耗尽虚拟机的使用内存,进而内存溢出,导致读取失败。还有,这种方式在网络读取时需要一次不受阻塞地读取完,容易因异常而中断导致读取失败。byte[] buff = new byte[1024],而这种方法的缓冲是固定大小的,不会出现这种情况,因为未知文件的大小是不确定的,所以一般建议使用这种方式。

评分

参与人数 1技术分 +1 收起 理由
黄奕豪 + 1 赞一个!

查看全部评分

回复 使用道具 举报
import java.io.*;

public class FileStreamDemo {

public static void main(String[] args) throws IOException {

//创建两个文件,face.gif是已经存在文件,newFace.gif是新创建的文件

File inFile = new File("face.gif");

File outFile = new File("newFace.gif");

//创建流文件读入与写出类

FileInputStream inStream = new FileInputStream(inFile);

FileOutputStream outStream = new FileOutputStream(outFile);

//通过available方法取得流的最大字符数

byte[] inOutb = new byte[inStream.available()];

inStream.read(inOutb);  //读入流,保存在byte数组

outStream.write(inOutb);  //写出流,保存在文件newFace.gif中

inStream.close();

outStream.close();

}

}

实例:读写任意大文件应用

因为byte数组最大存储值不超过64M,所以当一个文件大于60M 的时候,需要分开几个流操作。我们把上面的程序作一个修改,就可以写入任意大小的文件。这个程序应用了FileInputStream类的方法如下:

read(byte[] b,int off,int len)

把特定位置的流内容读入数组,已经读入byte[]数组的内容,会在流文件中删除。

程序运行的结果会产生一个新文件。

样例:

import java.io.*;

public class FileStreamDemo2 {

public static void main(String[] args) throws IOException {

//创建两个文件

File inFile = new File("tcty36.rm");

File outFile = new File("newtcty36.rm");

//最大的流为60Mb,当文件的容量大于60Mb的时候便分开流

final int MAX_BYTE = 60000000;

long streamTotal = 0;  //接受流的容量

int streamNum = 0;  //流需要分开的数量

int leave = 0;  //文件剩下的字符数

byte[] inOutb;  //byte数组接受文件的数据

//创建流文件读入与写出类

FileInputStream inStream = new FileInputStream(inFile);

FileOutputStream outStream = new FileOutputStream(outFile);

//通过available方法取得流的最大字符数

streamTotal = inStream.available();

//取得流文件需要分开的数量

streamNum = (int)Math.floor(streamTotal/MAX_BYTE);

//分开文件之后,剩余的数量

leave = (int)streamTotal % MAX_BYTE;

//文件的容量大于60Mb时进入循环

if (streamNum > 0) {

for(int i = 0; i < streamNum; ++i){

inOutb = new byte[MAX_BYTE];

//读入流,保存在byte数组

inStream.read(inOutb, 0, MAX_BYTE);

outStream.write(inOutb);  //写出流

outStream.flush();  //更新写出的结果

}

}

//写出剩下的流数据

inOutb = new byte[leave];

inStream.read(inOutb, 0, leave);

outStream.write(inOutb);

outStream.flush();

inStream.close();

outStream.close();

}

}
希望可以有帮助  固定数组缓冲区可以通过循环的方式读取任意大的文件 另一种方法 在文件过大的条件下 会过多占用电脑资源
回复 使用道具 举报
数组在哪里,在堆内存中,java的堆内存大小是有限度,如果的文件是2G的话,用byte[] buff = new byte[input.availabe()]的话,堆内存是装不下的。但是你用byte[] buff = new byte[1024],每次数组存满1024的字节以后,就会回头重存数组。
还有java的堆内存肯定小于你计算机的内存。
回复 使用道具 举报

available()
这个方法只有在读取的内容很少时,可以用。
还有因为它可以不受阻塞地读取的估计剩余字节数,但是在网速缓慢的网络上读取大文件时很可能会中断读取,导致失败。

建议使用byte[] buff=new byte[1024],在这里它作为缓冲区是固定长度的,所以不会出现以上的问题

回复 使用道具 举报
还有就是,avalible读取是一次就把所有的数据读取到缓冲区,而虚拟机的内存只有64M,所以在读取大文件时,很可能导致内存溢出.
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马