2 sinat 33645256 sinat_33645256 于 2016.02.12 20:34 提问

关于Java中FileInputStream类的一些新手疑问

在每次使用FileInputStream的read方法时,需要用到字节数组bytes和真实读取长度len,如代码:

 public static void read(){
        File file = new File("D:/学习/Android/代码/Workplace/Java_8_1_File/a.txt");
        try {
            //针对文件创建一个输入流
            InputStream in = new FileInputStream(file);
            byte[] bytes = new byte[1024*1024*10];//定义一个10MB的字节数组
            int len = -1;//每次真实读取的长度
            StringBuffer buf = new StringBuffer();

            try {
                while((len = in.read(bytes))!=-1){
                    buf.append(new String(bytes,0,len));
                }
                in.close();//关闭
                System.out.println(buf);
            } catch (IOException e) {
                e.printStackTrace();
            }

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }

,其中在循环里,buf.append那一句中,每一次都把0处len字节数加入到buf中,那么倘若文件的数据是:
01234
为何最后输出的结果不是:
001012012301234
呢?

2个回答

fk002008
fk002008   2016.02.12 21:43
已采纳

首先呢这个bytes是干什么的?
缓冲区,就是防止大数据量的时候,我们每次只读取一部分数据到缓冲区中进行操作
那么这个len又是什么呢?
它是实际的读取字节的数

你如果学过数据结构就知道这是一种线性表的思想
因为有时候读取的数据是不能填满这个bytes的,那么len就是实际的数

你抓住读取思想:
每次都是读取文件的bytes大小数据放到bytes数组中
所以取的时候自然是从bytes的0处去取
buf.append(new String(bytes,0,len));
加上len,用于防止最后一次的操作错误,最后一次取的数据实际长度是小于等于bytes的长度的,如果小于,那么bytes还残留着上次的数据。
所以使用len来读取最后一次实际取的数据。

建议去看看线性表

sinat_33645256
sinat_33645256 谢谢,我明白了,不过还没有学数据结构,我会去看一看的。
接近 2 年之前 回复
fk002008
fk002008 如果按照你的理解第一次bytes是ab,第二次bytes是abcd,依次下去这个bytes失去了缓冲的意义,建议你还是看看线性表,此处的bytes就是限制每次读文件的量,这样一个大文件可以分几次之后放入内存中处理,每次读取都是从头到尾填满整个bytes,如果填不满这个len就发挥作用了
接近 2 年之前 回复
fk002008
fk002008 然后第二次读文件那就是cd了,也就是说数组此时的东西是cd了,可不是把文件的东西追加到之前的ab的后面,所以还要从0开始截取bytes的数据
接近 2 年之前 回复
fk002008
fk002008 回复lambda-fk: 假设你bytes数组每次只能读取2个,len就是2,那么循环第一次读取的是ab,然后从bytes中0开始读取2个,
接近 2 年之前 回复
fk002008
fk002008 回复sweetstar86: 注意你读取文件的时候使用的是bytes,是按照数组容量来读取文件的,len是实际的读取个数,你现在把读文件和那个存入数组的操作弄混了
接近 2 年之前 回复
sinat_33645256
sinat_33645256 我的理解是,比如abcde这些数据,然后循环第一次截取了ab,第二次的时候,还是0处开始,那不会是ababcd吗
接近 2 年之前 回复
fk002008
fk002008 你把你文件的数据弄的大一些,或者你把缓冲区数组的长度调的小一点,能有3次以上的循环你就明白了
接近 2 年之前 回复
fk002008
fk002008 回复sweetstar86: 注意你是在循环中处理的,append从0开始buf.append(new String(bytes,0,len));那是指从数组的第0位开始截取len个元素,怎么会重复呢?
接近 2 年之前 回复
sinat_33645256
sinat_33645256 而且如果循环继续的话,那append每次从0开始不是会造成相同数据的叠加读出吗?
接近 2 年之前 回复
sinat_33645256
sinat_33645256 我试着把循环去掉之后,结果不出错也相同,这是为什么?观察debug也只是运行了一次循环。。。
接近 2 年之前 回复
caozhy
caozhy   Ds   Rxr 2016.02.12 21:50

一个是字符串,一个是字节数组,既然你是文本文件,就不应该用FileInputStream去读。

Csdn user default icon
上传中...
上传图片
插入图片
准确详细的回答,更有利于被提问者采纳,从而获得C币。复制、灌水、广告等回答会被删除,是时候展现真正的技术了!