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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 折纸时代 中级黑马   /  2013-2-3 12:19  /  1327 人查看  /  6 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 张向辉 于 2013-2-5 12:34 编辑

先上代码:
  1. /*
  2. 需求:
  3. 1.把电影文件按照10M每单位的大小分隔.
  4. 2.然后把电影合并,保证其可以正常观看.

  5. */
  6. import java.io.*;
  7. import java.util.*;
  8. class FilmSplit
  9. {
  10.         public static void filmSplit() throws IOException  //切割
  11.         {
  12.                 //new 字节输入流
  13.                 FileInputStream fis = new FileInputStream("F:\\1.MP4");
  14.                 //new 字节输出流
  15.                 FileOutputStream fos = null;
  16.                 //定义缓冲
  17.                 byte[] buf = new byte[1024*1024];
  18.                 //定义计数器
  19.                 int len = 0, time = 0, sum = 0;
  20.                 //此处while循环如何优化?
  21.                 while (sum < 4)  //限定次数,不产生多余空白文件
  22.                 {
  23.                         fos = new FileOutputStream("F:\\split\\"+ (sum++) + ".part");  //先产生目的流
  24.                         while ((time < 10) && ((len = fis.read(buf)) != -1))                //再存入数据. 限定10M
  25.                         {
  26.                                 time++;
  27.                                 fos.write(buf, 0, len);
  28.                         }
  29.                         fos.close();
  30.                         time = 0;
  31.                 }
  32.                 fis.close();
  33.         }
  34.         public static void merge() throws IOException  //合并
  35.         {
  36.                 //new vector集合
  37.                 Vector<FileInputStream> v = new Vector<>();
  38.                 //循环添加源
  39.                 for(int x = 0; x < 4; x++)
  40.                 {
  41.                         v.add(new FileInputStream("F:\\split\\"+ x + ".part"));
  42.                 }
  43.                 //获取Enumeration枚举
  44.                 Enumeration<FileInputStream> en = v.elements();
  45.                 //合并流
  46.                 SequenceInputStream sis = new SequenceInputStream(en);
  47.                 //输出流
  48.                 FileOutputStream fos = new FileOutputStream("F:\\split\\kongfu.rmvb");
  49.                 byte[] buf = new byte[1024];
  50.                 int len = 0;
  51.                 while((len = sis.read(buf)) != -1)
  52.                 {
  53.                         fos.write(buf, 0, len);
  54.                 }
  55.                 fos.close();
  56.                 sis.close();
  57.         }
  58.         public static void main(String[] args) throws IOException
  59.         {
  60.                 //filmSplit(); //切割
  61.                  merge();                //合并
  62.         }
  63. }
复制代码
自己写了个小程序,按照毕老师的思路,但是现在遇到个小问题.
文件按体积大小切割没有问题了,但是,无法自动的控制切割的次数.
总是,切割次数要手动按照源文件大小来设定,如果设定的多了,就会产生很多空白文件.
如果,外循环通过 (len = sis.read(buf)) != -1   来判断的话,
那么内部循环的数据一直在存储同一次的数据.
就是把第一次数组内的数据存储10次后,才读取第二次.  囧~!
有何方法可以控制外循环?  来保证资源的合理利用还有次数控制呢?

-----------------------------
想到一方法:
先获取媒体源的字节数,然后再除以要切割的体积.
值为int,所以再加1.  这样就刚好可以装下媒体数据,而不会产生多余文件.
但是这样感觉好麻烦...  

评分

参与人数 1黑马币 +9 收起 理由
Rancho_Gump + 9 赞一个!

查看全部评分

6 个回复

倒序浏览
本帖最后由 朱玉玺 于 2013-2-3 13:44 编辑

参考该帖子http://bbs.itheima.com/forum.php ... id=36506&highlight=一个IO流程序的问题
另外媒体切割,好像还涉及个位操作,记不太清了
回复 使用道具 举报
朱玉玺 发表于 2013-2-3 13:38
参考该帖子http://bbs.itheima.com/forum.php ... id=36506&highlight=一个IO流程序的问题
另外媒体切割, ...

不是相同的问题  ..

媒体切割和文件切割都一样,只是对于单位容量大小的控制不同.
回复 使用道具 举报
修改完毕,请楼主自测....
  1. /*
  2. 需求:
  3. 1.把电影文件按照10M每单位的大小分隔.
  4. 2.然后把电影合并,保证其可以正常观看.

  5. */
  6. import java.io.*;
  7. import java.util.*;
  8. class FilmSplit
  9. {
  10.             static int sum;
  11. static int count;
  12.         public static void filmSplit() throws IOException  //切割
  13.         {
  14.                 //new 字节输入流
  15.                     File file=new File("F:"+File.separator+"1.MP4");
  16.                 FileInputStream fis = new FileInputStream(file);
  17.                 //new 字节输出流
  18.                 FileOutputStream fos = null;
  19.                 //定义缓冲
  20.                 byte[] buf = new byte[1024*1024*count];
  21.                 //定义计数器
  22.                 int len = 0;
  23.                 //此处while循环如何优化?
  24.             
  25.                          //先产生目的流
  26.                         while (((len = fis.read(buf)) != -1))                //再存入数据. 限定10M
  27.                         {
  28.                                 fos = new FileOutputStream("F:"+File.separator+"split"+File.separator+ (sum++) + ".part");
  29.                                 fos.write(buf, 0, len);
  30.                                 fos.close();
  31.                         }
  32.                      fis.close();
  33.         }
  34.         public static void merge() throws IOException  //合并
  35.         {
  36.                 //new vector集合
  37.                 Vector<FileInputStream> v = new Vector<>();
  38.                 //循环添加源
  39.                 for(int x = 0; x < sum; x++)
  40.                 {
  41.                         v.add(new FileInputStream("F:"+File.separator+"split"+File.separator+ x + ".part"));
  42.                 }
  43.                 //获取Enumeration枚举
  44.                 Enumeration<FileInputStream> en = v.elements();
  45.                 //合并流
  46.                 SequenceInputStream sis = new SequenceInputStream(en);
  47.                 //输出流
  48.                 FileOutputStream fos = new FileOutputStream("F:"+File.separator+"split"+File.separator+"kongfu.rmvb");
  49.                 byte[] buf = new byte[1024];
  50.                 int len = 0;
  51.                 while((len = sis.read(buf)) != -1)
  52.                 {
  53.                         fos.write(buf, 0, len);
  54.                 }
  55.                 fos.close();
  56.                 sis.close();
  57.         }
  58.         public static void main(String[] args) throws IOException
  59.         {
  60.                 filmSplit(); //切割
  61.                  merge();                //合并
  62.         }
  63. }
复制代码
逻辑混乱,直接去掉外外循环,用外部变量控制每次切割生成单个文件的数据容量.....

评分

参与人数 1黑马币 +9 收起 理由
Rancho_Gump + 9

查看全部评分

回复 使用道具 举报
本帖最后由 司懿卓 于 2013-2-3 21:17 编辑
赵文 发表于 2013-2-3 20:34
修改完毕,请楼主自测....逻辑混乱,直接去掉外外循环,用外部变量控制每次切割生成单个文件的数据容量.... ...

呵呵..

如果我需要1GB 为单位的话,是不是要我的内存爆掉??  
不过还是多谢了.  我之前找到方法了.. 但是感觉不是很简洁..
我可以控制  while ((time < 10) && ((len = fis.read(buf)) != -1))   中time的次数来保证单位大小. 这样不涉及内存的溢出问题.
另外  int num = 1024*1024*10;  中的10 可以和time条件是一个参数,这样感觉更好点.
  1. public static void filmSplit() throws IOException  //切割
  2.         {
  3.                 //new 字节输入流
  4.                 FileInputStream fis = new FileInputStream("F:\\split\\1.MP4");
  5.                 //new 字节输出流
  6.                 FileOutputStream fos = null;
  7.                 //定义计数器
  8.                 int len = 0, time = 0, sum = 0;
  9.                 //定义缓冲
  10.                 int num = 1024*1024*10;
  11.                 byte[] buf = new byte[num/10];
  12.                
  13.                 int se = fis.available()/num + 1;
  14.                 System.out.println(se);
  15.                 for (int i = 0; i < se; i++)  //限定次数,不产生多余空白文件
  16.                 {
  17.                         fos = new FileOutputStream("F:\\split\\"+ (sum++) + ".part");  //先产生目的流
  18.                         while ((time < 10) && ((len = fis.read(buf)) != -1))                // 再存入数据. 限定10M
  19.                         {
  20.                                 time++;
  21.                                 fos.write(buf, 0, len);
  22.                         }
  23.                         fos.close();
  24.                         time = 0;
  25.                 }
  26.                 fis.close();
  27.         }
复制代码
回复 使用道具 举报
司懿卓 发表于 2013-2-3 21:08
呵呵..

如果我需要1GB 为单位的话,是不是要我的内存爆掉??  

把你找到得方法贴上来,大家共勉....
回复 使用道具 举报
本帖最后由 司懿卓 于 2013-2-3 21:24 编辑
赵文 发表于 2013-2-3 21:13
把你找到得方法贴上来,大家共勉....

恩 ,已经贴上来了..  帮忙看看有什么不到之处..
谢谢啦.


几处需要修改:
1. 把int num = 1024*1024*10; 中的10 和 time的控制 声明成 一个参数.
2. fos.write(buf, 0, len); 语句后添加flush方法,这样更能避免内存溢出问题.  
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马