黑马程序员技术交流社区
标题:
经过一上午的努力终于弄明白了,有错误还请指出啊
[打印本页]
作者:
赵晓东
时间:
2013-3-17 11:07
标题:
经过一上午的努力终于弄明白了,有错误还请指出啊
本帖最后由 赵晓东 于 2013-3-17 11:11 编辑
/*IO_MyBufferedInputStream*/
/*
需求:模拟字节读取流缓冲区
思路:字节读取流缓冲区是字节流在硬盘上读取一批数据然后存到数组中,计数器记录
住当前批次数据的个数,然后数组再通过指针来读取数据,每读取一个数据,计数器就
减一,直到读完当前批次的数据,缓冲区数组再次使用字节流在硬盘上读取一批数据,
以此类推,直到字节流把目标地址中的硬盘数据读完为止
步骤:
①自定义字节读取缓冲区类MyBufferedInputStream,初始化该类时接收一个字节流对象
FileInputStream in;
②定义计数器变量count和指针变量post
③定义接收字符的数组buf
④定义关闭资源对象myclose
*/
import java.io.*;
class MyBufferedInputStream
{
FileInputStream in; //定义字节流对象的引用
int count = 0; //定义计数器
int post = 0; //定义指针
byte b = 0; //定义取出数组中数据的变量
byte[] buf = new byte[1024]; //定义缓存数组
MyBufferedInputStream(FileInputStream in)
{
this.in = in; //接收一个字节流对象
}
public int myRead() throws IOException
{
if (count ==0) //如果计数器为0则说明缓存数组中没有数据,这时接收一批数据
{
count = in.read(buf); //接收一批数据存入到缓存数组中,并记录住个数
post = 0; //指针为0,这里强调一下,如果不把指针重置为0的话,那么读取下一批次的时候,指针会越界
b = buf[post]; //读取数据
count--; //计数器自减,因为读取出一个元素,元素个数就会减少一个,直到把数组中的元素读完,才接收下一批次的数据
post++; //指针累加,读取数组中的数据
return b&255; //这里是(int) b强制转换了byte型的b
/*
为什么把byte型的b 强制转换成int型的?
因为return 返回的是 int类型的
为什么不把返回值定义成byte型的呢?
因为如果文件读取到末尾返回的是-1,这个-1 是int型的
那为什么又要让强制转换后的b &255呢?
mp3的字节二进制文件有可能是1111-1111这样排列的,而这个值转换成十进制后是-1
byte型(8位):1111-1111(-1)
强制转换后
int型(32位):1111-1111 1111-1111 1111-11111 111-1111 (-1)
return返回-1程序就不会读取字符缓冲区的数据了,但是硬盘上的数据没有读完
这时我们就让提升后的int型 b与上255
1111-1111 1111-1111 1111-1111 1111-1111
&0000-0000 0000-0000 0000-0000 1111-1111
————————————————————
0000-0000 0000-0000 0000-0000 1111-1111 ——>保留的是后8位,也就是byte型数据的值,
write写入时会自动将int型强制转换成byte型,到时候保留的就是,数组缓冲区中byte型的数据
*/
}
else if (count >0) //计数器不为0,说明数组中的元素没有完全取出,继续取出操作
{
b = buf[post];
count--;
post++;
return b&0xFF;
}
else
return -1; //如果read() 返回-1,则硬盘上的数据已经读取完毕,返回-1
}
public void myClose() throws IOException
{
in.close(); //关闭资源
}
}
class MyBufferedInputStreamDemo
{
public static void main(String[] args)
{
long start = System.currentTimeMillis();
CopyMp3();
long end = System.currentTimeMillis();
System.out.println(end-start+"毫秒");
}
public static void CopyMp3()
{
MyBufferedInputStream mbis = null;
BufferedOutputStream bos = null;
int len = 0; //定义为int型,不能定义成byte,因为要接收文件读取结束的-1,而-1 是int 型的
try
{
mbis = new MyBufferedInputStream(new FileInputStream("d:\\1.mp3")); //使用自定义的缓冲区读取数据,传入一个字节流对象
bos = new BufferedOutputStream(new FileOutputStream("d:\\3.mp3"));
while ((len = mbis.myRead()) != -1)
{
bos.write(len);
}
}
catch (IOException e)
{
System.out.println(e.toString());
}
finally
{
try
{
if(mbis != null)
mbis.myClose();
}
catch (IOException e)
{
System.out.println(e.toString());
}
try
{
if(bos != null)
bos.close();
}
catch (IOException e)
{
System.out.println(e.toString());
}
}
}
}
复制代码
作者:
VOIDMAIN
时间:
2013-3-17 11:34
你只是在模拟缓冲区,所以我觉得有一个地方你没说准确,就是你说len=0要定义为int类型是因为-1的原因,这里我的理解是:缓冲流是包装了FileInputstream流中的read方法实现的对文件读取操作,而FileInputStream的read方法本身会返回一个int类型的数据,所以不在缓冲流中不存在提升的问题了,这个提升在FileIputstream中已经完成;
其实缓冲区就是帮助我们定义了一个大小合适的数组来缓冲接收read方法的数据,而只要自己的byte数组大小合适,直接用FileIputstream的效率并不比加缓冲区的效率低,最后理解一下,自己定义一个byte数组接收数据相当于自己修了一个水池,而加入缓冲区,则系统又默认给了一个水池,这样就有两个水池了,到底是一个水池好,还是两个水池好,并不一定,但是可以肯定的是一定要有水池做缓冲。
作者:
赵晓东
时间:
2013-3-17 14:25
VOIDMAIN 发表于 2013-3-17 11:34
你只是在模拟缓冲区,所以我觉得有一个地方你没说准确,就是你说len=0要定义为int类型是因为-1的原因,这里 ...
恩,说的,很好,忘记read的返回值类型是int了{:3_49:}
作者:
李晓峰
时间:
2013-3-19 18:01
路过。。。
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2