A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

本帖最后由 小黑子 于 2014-9-23 15:23 编辑

自己写了个字节流缓冲区,复制歌曲,结果出现了死循环,不知道问题出在哪了…………
  1. /*
  2.         自定义一个字节流缓冲区
  3. */

  4. import java.io.IOException;
  5. import java.io.InputStream;
  6. import java.io.FileInputStream;
  7. import java.io.FileOutputStream;


  8. class MyBufferedInputStream
  9. {
  10.         private InputStream is;
  11.         int pos=0,count=0;
  12.         byte[] bufb = new byte[1024];

  13.         MyBufferedInputStream(InputStream is)
  14.         {
  15.                 this.is = is;
  16.         }

  17.         public int myRead() throws IOException
  18.         {
  19.                 //当count==0时,需从硬盘中取数据到缓冲区(即bufb中)。
  20.                 if(count==0)
  21.                 {
  22.                         count = is.read(bufb);
  23.                         System.out.println("if1 count = "+count);
  24.                         if(count<0)//当count<0,说明硬盘中已无数据,不必读取,故返回-1
  25.                                 return -1;
  26.                         pos = 0;//每重新装载一次缓冲区,需将pos置0
  27.                 }

  28.                 //当count>0时,需读取缓冲区的数据
  29.                 if(count>0)
  30.                 {
  31.                         byte b = bufb[pos++];
  32.                         count--;
  33.                         System.out.println("if2 count = "+count);
  34.                         return b&255;//        先将b由byte转为int,然后保留低8位,高位置0               
  35.                 }

  36.                 return -1;//?????????????
  37.         }

  38.         public void close() throws IOException
  39.         {
  40.                 is.close();
  41.         }
  42. }


  43. class MyBufferedInputStreamDemo
  44. {
  45.         public static void main(String[] args) throws IOException
  46.         {
  47.                 long start = System.currentTimeMillis();
  48.                 copy();
  49.                 long end = System.currentTimeMillis();
  50.                 System.out.println("time = "+(end-start));
  51.         }

  52.         //复制歌曲
  53.         public static void copy() throws IOException
  54.         {
  55.                 MyBufferedInputStream mbis = null;
  56.                 FileOutputStream fos = null;
  57.                 try
  58.                 {
  59.                         mbis = new MyBufferedInputStream(new FileInputStream("d:\\G.E.M. 邓紫棋 - 后会无期.mp3"));
  60.                         fos = new FileOutputStream("f:\\邓紫棋.mp3");
  61.                         int b;
  62.                         while((b=mbis.myRead())!=-1)
  63.                         {
  64.                                 fos.write(b);
  65.                         }
  66.                 }
  67.                 catch (IOException e)
  68.                 {
  69.                         throw new IOException("读写异常");
  70.                 }
  71.                 finally
  72.                 {
  73.                         if(mbis!=null)
  74.                                 try
  75.                                 {
  76.                                         mbis.close();
  77.                                 }
  78.                                 catch (IOException e)
  79.                                 {
  80.                                         throw new IOException("读资源关闭异常");
  81.                                 }
  82.                         if(fos!=null)
  83.                                 try
  84.                                 {
  85.                                         fos.close();
  86.                                 }
  87.                                 catch (IOException e)
  88.                                 {
  89.                                         throw new IOException("写资源关闭异常");
  90.                                 }
  91.                 }
  92.         }
  93. }
复制代码



评分

参与人数 1技术分 +1 收起 理由
陈君 + 1

查看全部评分

10 个回复

正序浏览
小黑子 发表于 2014-9-23 15:15
非常感谢。但是你这个写的是和毕老师的差不多的。
我现在就是想知道我的代码哪里错了。是我的代码在逻辑 ...

你的代码没有错。输出流选的类导致效率低
回复 使用道具 举报
Huberry 发表于 2014-9-23 10:39
程序是没有死循环的,是你这程序效率实在是太慢,在我电脑上复制10K的数据就要2秒,你复制一首3M的MP3文件 ...

果然是运行效率低,谢谢啦~~
回复 使用道具 举报
careit 发表于 2014-9-23 10:55
修改的直接写在注释里面了

非常感谢。但是你这个写的是和毕老师的差不多的。
我现在就是想知道我的代码哪里错了。是我的代码在逻辑结构是有问题么?
我设想的是,为了避免代码重复,所以在第1个if中只将数据读取到缓冲区,在第2个中再从缓冲区存储到文件中。难道这样设计会丢失第一个数据?
回复 使用道具 举报
careit 中级黑马 2014-9-23 10:55:57
8#
修改的直接写在注释里面了

  1. package test;

  2. import java.io.BufferedOutputStream;
  3. import java.io.FileInputStream;
  4. import java.io.FileOutputStream;

  5. /*
  6. 自定义一个字节流缓冲区
  7. */
  8. import java.io.IOException;
  9. import java.io.InputStream;

  10. class MyBufferedInputStream {
  11.         private InputStream is;
  12.         int pos = 0;
  13.         int count = 0;
  14.         byte[] bufb = new byte[1024];

  15.         MyBufferedInputStream(InputStream is) {
  16.                 this.is = is;
  17.         }

  18.         public int read() throws IOException {
  19.                 // 当count==0时,需从硬盘中取数据到缓冲区(即bufb中)。
  20.                 if (count == 0) {
  21.                         count = is.read(bufb);
  22.                         // System.out.println("if1 count = " + count);
  23.                         if (count < 0) { // 当count<0,说明硬盘中已无数据,不必读取,故返回-1
  24.                                 return -1;
  25.                         }
  26.                         pos = 0; // 每重新装载一次缓冲区,需将pos置0
  27.                         count--;// 重新一次读到数据、自然返回第一个啊
  28.                         return bufb[pos] & 255;
  29.                 }
  30.                 else{
  31.                 // 当count>0时,需读取缓冲区的数据
  32.                 if (count > 0) {
  33.                         // 先把pos 自加一次,在取值。不然还是0.毕老师是在上面pos++
  34.                         byte b = bufb[++pos];// 改为byte b = bufb[++pos]
  35.                         count--;
  36.                         // System.out.println("if2 count = " + count);
  37.                         return b & 255; // 先将b由byte转为int,然后保留低8位,高位置0
  38.                 }
  39.                 }
  40.                 return -1; // ?????????????这里是逻辑上不会被执行到的,为了语法正确
  41.         }

  42.         public void close() throws IOException {
  43.                 is.close();
  44.         }
  45. }

  46. public class MyBufferedInputStreamDemo {
  47.         public static void main(String[] args) throws IOException {
  48.                 long start = System.currentTimeMillis();
  49.                 copy();

  50.                 long end = System.currentTimeMillis();
  51.                 System.out.println("time = " + (end - start));
  52.         }

  53.         // 复制歌曲
  54.         public static void copy() throws IOException {
  55.                 MyBufferedInputStream mbis = null;
  56.                 FileOutputStream fos = null;
  57. //                BufferedOutputStream fos=null;
  58.                 try {
  59.                         // mbis = new MyBufferedInputStream(new FileInputStream(
  60.                         // "d:\\G.E.M. 邓紫棋 - 后会无期.mp3"));
  61.                         // fos = new FileOutputStream("f:\\邓紫棋.mp3");

  62.                         mbis = new MyBufferedInputStream(new FileInputStream("f:\\1.mp3"));
  63.                         fos = new FileOutputStream("f:\\2.mp3");
  64. //                        fos=new BufferedOutputStream(new FileOutputStream("f:\\2.mp3") );
  65.                        
  66.                         //复制完MP3 之后一定要查看一下文件大小。看字节,最好在复制一次图片
  67.                         //测试时发现,mp3 错误了一点也可以播放,你可以把bufb[++pos];改为 bufb[pos++]
  68.                         //文件大小一样,MP3可以播放,但声音失真了。复制图片直接打不开
  69. //                        mbis = new MyBufferedInputStream(new FileInputStream("f:\\fis.jpg"));
  70. //                        fos = new FileOutputStream("f:\\fos.jpg");
  71. //                        fos=new BufferedOutputStream(new FileOutputStream("f:\\2.mp3") );
  72.                        
  73.                         int b;

  74.                         while ((b = mbis.read())!=-1) {
  75.                                 fos.write(b);
  76.                         }
  77.                 } catch (IOException e) {
  78.                         throw new IOException("读写异常");
  79.                 } finally {
  80.                         if (mbis != null) {
  81.                                 try {
  82.                                         mbis.close();
  83.                                 } catch (IOException e) {
  84.                                         throw new IOException("读资源关闭异常");
  85.                                 }
  86.                         }

  87.                         if (fos != null) {
  88.                                 try {
  89.                                         fos.close();
  90.                                 } catch (IOException e) {
  91.                                         throw new IOException("写资源关闭异常");
  92.                                 }
  93.                         }
  94.                 }
  95.         }
  96. }
复制代码

评分

参与人数 1技术分 +1 收起 理由
陈君 + 1

查看全部评分

回复 使用道具 举报
程序是没有死循环的,是你这程序效率实在是太慢,在我电脑上复制10K的数据就要2秒,你复制一首3M的MP3文件就需要10分钟,所以你以为是死循环

你这定义的字节流缓冲区还不如没有的好, 你这个缓冲区虽然说把从源读来的数据缓存了,但是往目标文件写的时候效率非常低,每写一个字节,就需要判断count的条件,判断语句是非常影响效率的。而最拖垮你代码效率的是你那两条打印语句,你这每写一个字节就需要执行一次打印“if2“,并且每读1K的数据就要执行一次打印“if1”. 你把打印语句去掉,10几秒应该可以复制完一首歌,你可以看到程序结束,至于自定义字节流缓冲区我建议你再看看视频,琢磨琢磨吧。

评分

参与人数 1技术分 +1 收起 理由
陈君 + 1

查看全部评分

回复 使用道具 举报
大神在哪里?求指导****
回复 使用道具 举报
苏乞儿 发表于 2014-9-23 00:02
应该是定义的MyRead ()方法的问题,读文件怎么没用循环,只用了if?而且count>0的情况能不能被执行还是个 ...

循环在调用MyRead时用的,而且count>0肯定可以执行到。
回复 使用道具 举报
fantacyleo 发表于 2014-9-23 00:25
程序正常结束~~

你的确实可以正常结束么?我刚又运行了一下,还是死循环:'(
回复 使用道具 举报
程序正常结束~~
回复 使用道具 举报
应该是定义的MyRead ()方法的问题,读文件怎么没用循环,只用了if?而且count>0的情况能不能被执行还是个问题。。。。
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马