仿BufferedInputStream自定义包装类MyBufferedInputStream如下:
class MyBufferedInputStream {
private InputStream in;
private byte[] buf = new byte[1024];
private int pos = 0, count = 0;
MyBufferedInputStream(InputStream in) {
this.in = in;
}
public int myRead() throws IOException {
if (count == 0) {
count = in.read(buf);
pos=0;
if(count<0)
return -1;
byte b = buf[pos];
count--;
pos++;
return b;
} else if (count > 0) {
byte b=buf[pos];
count--;
pos++;
return b;
}
return -1;
}
public void myClose()throws IOException{
in.close();
}
}
public class CopyMp3 {
public static void main(String[] args) throws IOException {
MyBufferedInputStream bis=new MyBufferedInputStream(new FileInputStream("dream.mp4"));
BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream("dream_copy.mp4"));
int ch=0;
int num=0;
while((ch=bis.myRead())!=-1){
bos.write(ch);
num++;
}
bis.myClose();
bos.close();
}
测试发现并不能拷贝文件,从语法跟逻辑上貌似都找不到问题,但是仔细观察会发现,自定义类的myRead()方法要求返回int类型,而此函数的return b返回的b却是byte类型。这两个类型的区别byte是八位,而int是32位。因为在计算机内部,数据是由0和1组成,有可能出现11111111111000000101001010连续为1或0的情况,当byte类型的b读取一个字节时,如果读到的是1111-1111,那么翻译成十进制就是-1,即使由byte升级为int类型,也是-1,所以在while循环的时候就会停止下来。解决方案如下:
修改前byte型-1为11111111升级为int型后补1变为11111111-11111111-11111111-11111111,现在如果把补1变为补0,则结果成了00000000-00000000-00000000-11111111,就不是-1了,而是255了,这样就实现了既保住原数据也避免了-1的情况。不要担心提升之后数据量增加,在read读到32位之后,write方法只会讲低8位写入文件,因此前面补的0也就不会写入文件了,拷贝后的文件就与原文件完全相同了。实现补0效果的方法是与运算:b&0xff或者b&255。本题中在所有return b的地方都做如下修改return b&0xff就行了