黑马程序员技术交流社区
标题:
自定义字节的缓冲,帮忙理下逻辑思维有点乱
[打印本页]
作者:
李健09
时间:
2013-10-2 11:13
标题:
自定义字节的缓冲,帮忙理下逻辑思维有点乱
本帖最后由 李健09 于 2013-10-8 21:53 编辑
package com.IO;
/*
public static void copy_2() throws IOException
{
MyBufferedInputStream bufis=new MyBufferedInputStream(new FileInputStream("D:\\歌曲\\红颜白头到.wma"));
BufferedOutputStream bufos=new BufferedOutputStream(new FileOutputStream("D:\\歌曲\\copy2.wma"));
int by=0;
//sop("第一个字节"+bufis.myRead()); //此时 显示的结果字节数很少 第一个字节48
while((by=bufis.myRead())!=-1)
{
bufos.write(by);
}
bufos.close();
bufis.myClose();
}
----sop("第一个字节"+bufis.myRead()); //此时 显示的结果字节数很少 第一个字节48,那么我们的程序接近-1的时间就会很快
public int myRead() throws IOException
{
//通过in对象读取硬盘上的数据,并存储buf中。
if(count==0)
{
count=in.read(buf);//这里表示in.read()读取读取硬盘上的数据,并存储于buf中的个数
if(count<0)
return -1;
pos=0;
byte b=buf[pos];
count--;
pos++;
return b;
}
else if(count>0)
{
byte b=buf[pos];
count--;
pos++;
return b;
}
return -1;
}
----当读到byte(b)值为111111时,返回的是-1 转换成int 还是-1 ;copy_2()方法就会停止,程序停止运行,复制也停止运行,所以没有完全复制完成
-1 ----->1111-1111二进制
byte:-1------>int:-1;
byte:-1
1111-1111
int:-1
1111-1111 1111-1111 1111-1111 1111-1111
那为什么myRead()方法的返回值用的是int呢?
在读到连续11111111的时候为了避免碰到-1的这种情况和我判断的结束截止标记-1相同所以我可以在保留原11111111的基础上再转成int类型的时候
11111111前面补零而不补1,避免类提前使结束标记变成-1;使原数据没有变化并避免提前出现-1的情况
byte[b]:-1
1111-1111
byte[b]---->int类型 那不还是-1吗?因为我们在1111-1111前面补得是1导致的,那么我们只要在前面补0即可保留原字节数据不免又可以避免-1的
出现,那么我们怎么补0呢?
0000-0000 0000-0000 0000-0000 1111-1111 ---->255
int 类型的-1 取最低8位(-1&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
所以b&255
*/
import java.io.*;
class MyBufferedInputStream
{
private InputStream in;
private byte[] buf=new byte[1024];
int pos=0,count=0;
MyBufferedInputStream(InputStream in)
{
this.in=in;
}
//一次读一个字节,从缓冲区(字节数组)获取
public int myRead() throws IOException
{
//通过in对象读取硬盘上的数据,并存储buf中。
if(count==0)
{
count=in.read(buf);//这里表示in.read()读取读取硬盘上的数据,并存储于buf中的个数
if(count<0)
return -1;
pos=0;
byte b=buf[pos];
count--;
pos++;
return b&255;
}
else if(count>0)
{
byte b=buf[pos];
count--;
pos++;
return b&0xff;//0xff 255的16进制表现形式
}
return -1;
}
public void myClose() throws IOException
{
in.close();
}
}
public class MyBufferedInputStreamDemo
{
public static void main(String[] args) throws IOException
{
long start =System.currentTimeMillis();
copy_2();
long end=System.currentTimeMillis();
sop((end-start)+"毫秒");
}
public static void copy_2() throws IOException
{
MyBufferedInputStream bufis=new MyBufferedInputStream(new FileInputStream("D:\\歌曲\\红颜白头到.wma"));
BufferedOutputStream bufos=new BufferedOutputStream(new FileOutputStream("D:\\歌曲\\copy2.wma"));
int by=0;
//sop("第一个字节"+bufis.myRead());
while((by=bufis.myRead())!=-1)
{
bufos.write(by);
}
bufos.close();
bufis.myClose();
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}
复制代码
问题1:sop("第一个字节"+bufis.myRead()); 我的这段代码输出的是第一个字节48是表示过48个字节就是结束标记-1吗?
问题2:我上面注释整理的笔记思路对吗?还有怎么是b&255,这里的b不是byte类型的吗?不是int类型的取最低8位吗?这时的怎么可以取最低8位?
作者:
潘才新
时间:
2013-10-2 19:59
达人们速来
作者:
hanfei2511
时间:
2013-10-4 05:40
问题1:sop("第一个字节"+bufis.myRead()); 我的这段代码输出的是第一个字节48是表示过48个字节就是结束标记-1吗?
问题2:我上面注释整理的笔记思路对吗?还有怎么是b&255,这里的b不是byte类型的吗?不是int类型的取最低8位吗?这时的怎么可以取最低8位?
第一个问题:
不是的,首先myRead()返回的是一个字节的数据(当然是以int类型返回的)
public int myRead() throws IOException
{
if(count==0)
{
count=in.read(buf);//因为你定义的buf的长度是1024,所以,此处的count值是1024,即当count等于0时,会从输入流读取1024个字节的数据,存储在buf数组中,如果你的文件大小小于1024字节,那么就会占用小于1024字节的数组空间,如果大于1024那么当elseif语句中count自减等于0后,会重新回到if语句块,再次进行上述相同的过程。如果读到了文件的结尾,返回-1
if(count<0)
return -1;
pos=0;
byte b=buf[pos];//b存储的是buf中第一个字节的数据
count--;//此时count==1023,所以下次调用myRead方法时,会执行elseif 部分语句。如果读到文件末尾,返回-1
pos++;//pos加一之后,指向buf数组中的下一个位置。
return b&255;//以int类型将b的数据返回。
}
else if(count>0)
{
byte b=buf[pos];
count--;
pos++;
return b&0xff;//0xff
}
return -1;
}
所以你在后面的while循环中调用myRead方法时,每一次返回的是当前字节的数据,你第一次调用返回的48表示当前字节数据是48,而不是48字节的数据,通过上面分析,我们也知道读完这个字节数据之后,也不是
结束标记-1,而是buf数组存储的下一字节的数据。除非你的文件只有一字节的数据。你可以在
copy_2()方法的sop语句后多加几条sop语句看下48后面的几个字节的 数据内容是什么。
第二个问题:
因为write()方法是以int类型写入文件的,所以我们
需要
将读取的byte类型数据转换成int类型。如果不进行&255计算,那么java会通过补码来进行自动转换,就会出现你在注释中说到的文件提前终止(出现-1)的情况,当进行
&255或&
0xff就会没问题了。所以你的注释部分还是对的。
至于“
还有怎么是b&255,这里的b不是byte类型的吗?
不是int类型的取最低8位吗?这时的怎么可以取最低8位?
”不太明白你疑惑的是什么,&是按位与,是利用二进制进行运算的,这里原本8位的b,在其前面补充1,到32位,和32位表示的255进行与运算,结果自然是保存了b原始8位的数据信息,只是这时在其最高位前加了24个零而已。
不知有没有讲明白,希望对您有帮助。
作者:
黄文伯
时间:
2013-10-8 18:20
亲,如问题已解决请将分类的“未解决”改为“已解决”。
以后的问题贴也要及时更改分类哦~
作者:
李健09
时间:
2013-10-8 21:50
本帖最后由 李健09 于 2013-10-8 21:52 编辑
hanfei2511 发表于 2013-10-4 05:40
问题1:sop("第一个字节"+bufis.myRead()); 我的这段代码输出的是第一个字节48是表示过48个字节就是结束标 ...
谢谢:):)
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2