自定义包装类并不能成功拷贝文件的原因分析

来源:互联网 发布:js的containskey方法 编辑:程序博客网 时间:2024/06/04 23:33

仿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就行了