黑马程序员技术交流社区

标题: IO流中关于图片分割和合并的问题,邪了! [打印本页]

作者: 刘俊佳    时间: 2012-7-16 12:44
标题: IO流中关于图片分割和合并的问题,邪了!
本帖最后由 刘俊佳 于 2012-7-16 13:48 编辑

这是代码:

package practice;
import java.util.*;
import java.io.*;


public class SplitFile {
public static void main(String[] args) throws IOException
{
  //splitFile();
  merge();
}

public static void merge() throws IOException
{
  ArrayList<FileInputStream> a1=new ArrayList<FileInputStream>();
  
  for(int x=1;x<=3;x++)
  {
   a1.add(new FileInputStream("d:\\java1223\\splitfiles\\"+x+".part"));
  }
  
  final java.util.Iterator<FileInputStream> it=a1.iterator();
  
  Enumeration<FileInputStream> en=new Enumeration<FileInputStream>()
  {
     public boolean hasMoreElements()
  {
   return it.hasNext();
  }
     public FileInputStream nextElement()
     {
      return it.next();
     }
  };
  
  SequenceInputStream sis=new SequenceInputStream(en);
  FileOutputStream fos=new FileOutputStream("d:\\java1233\\splitfiles\\0.gif");
     
  byte[] buf=new byte[1024*1024];
  int len=0;
  while((len=sis.read(buf))!=-1)
  {
   fos.write(buf,0,len);
  }
  fos.close();
  sis.close();
  
}

public static void splitFile()throws IOException
{
  FileInputStream fis=new FileInputStream("d:\\1.gif");
  
  FileOutputStream fos=null;
  
  byte[] buf=new byte[1024*1024];
  
  int len=0;
  int count=1;
  while((len=fis.read(buf))!=-1)
  {
   
   fos=new FileOutputStream("d:\\java1223\\splitfiles\\"+(count++)+".part");
      fos.write(buf,0,len);
      fos.close();
        
  }
  fis.close();
   
}
}







W6_1~A}X}4IP5~3@}CL2N(E.jpg (18.67 KB, 下载次数: 41)

运行分割图片代码时显示只分割了变成一张图片

运行分割图片代码时显示只分割了变成一张图片

)ZWTV)S$U]B7R5`JVJRCI(L.jpg (62.01 KB, 下载次数: 37)

运行图片合并的代码,报错如下:

运行图片合并的代码,报错如下:

作者: 王冰    时间: 2012-7-16 12:52
你这种情况应该是分割的文件  0.gif  过小,没有分割成3部分,建议你把
byte[] buf=new byte[1024*1024];这句中的1024*1024改小些,文件分割成3部分就能成功了,
或者你找一个2M以上不到3Md的图片来分割,这样应该也行
作者: 牛少锋    时间: 2012-7-16 12:58

byte[] buf=new byte[1024*1024];   //这里你把缓存区定义成1M了,定义的缓冲区定义大了
                                  一个图片才多大,一般几百KB的,你一次把他写完了,所以图片根本没有被分割到
                                 所以写到硬盘上的只有一个,也就是1.part,所以找不到2.part

                                 解决方法: byte[] buf=new byte[1024*1024]; 把这个该小点,例如 byte[] buf=new byte[1024*35];也就是35KB
                                                               这个大小可以根据图片大小来定,想分成几部分,就把缓存区定义为  图片大小/4   4代表要分割四部分,byte[] buf=new byte[1024*(图片大小/4 )];
  int len=0;
  int count=1;
  while((len=fis.read(buf))!=-1)
  {
   
   fos=new FileOutputStream("d:\\java1223\\splitfiles\\"+(count++)+".part");
      fos.write(buf,0,len);
      fos.close();
作者: 张世威    时间: 2012-7-16 13:32
1、分割文件,要首先确认分割的粒度,即byte[]buf 的大小。
2、根据这个粒度,将一个大文件分成几个小文件,
  3、你这个代码里面,图片文件可能不到1M,而你要按照1M来切割.就像1m的尺子,你非要切成几个2m的尺子,这怎么切?自然切割后还是那个1m的尺子了,就像没有切
4、你把你生成的那个1.part 改名成1.gif,看可不可以打开?
5解决思路:保证图片大于切割粒度
  ①换个大图片
  ②把粒度改小点buf改小点
作者: 蒋映辉    时间: 2012-7-16 13:37
楼主先百度一下图片格式看看  我把我以前做的一个图片编辑的代码发给你参考一下
  1. package img;

  2. import java.awt.Graphics;
  3. import java.io.IOException;

  4. import img.data;

  5. public class imgtostring {

  6.     Graphics g;
  7.    
  8.   
  9.     public data imgtostring(){
  10.             data d=new data();
  11.            
  12.              try {   
  13.              // 通过bmp文件地址创建文件输入流对象   
  14.              java.io.FileInputStream fin = new java.io.FileInputStream(   
  15.                      "img.bmp");   
  16.    
  17.              // 根据文件输入流对象创建原始数据输入对象   
  18.              // 这里既可以用原始数据输入流来读取数据,也可以用缓冲输入流来读取,后者速度相比较快点。   
  19. //           java.io.DataInputStream bis = new java.io.DataInputStream(fin);   
  20.    
  21.              java.io.BufferedInputStream bis = new java.io.BufferedInputStream(   
  22.                      fin);   
  23.    
  24.              // 建立两个字节数组来得到文件头和信息头的数据   
  25.              byte[] array1 = new byte[14];   
  26.              bis.read(array1, 0, 14);   
  27.    
  28.              byte[] array2 = new byte[40];   
  29.              bis.read(array2, 0, 40);
  30.             
  31.    
  32.              // 翻译bmp文件的数据,即将字节数据转化为int数据   
  33.              // 通过翻译得到位图数据的宽和高   
  34.              d.width = ChangeInt(array2, 7);   
  35.              d.height = ChangeInt(array2, 11);   
  36.    
  37.              // 调用可以将整个位图数据读取成byte数组的方法   
  38.              d.red = new int[d.height][d.width];   
  39.              d.green = new int[d.height][d.width];   
  40.              d.blue = new int[d.height][d.width];   
  41.       
  42.              // 通过计算得到每行计算机需要填充的字符数。   
  43.              // 为什么要填充?这是因为windows系统在扫描数据的时候,每行都是按照4个字节的倍数来读取的。   
  44.              // 因为图片是由每个像素点组成。而每个像素点都是由3个颜色分量来构成的,而每个分量占据1个字节。   
  45.              // 因此在内存存储中实际图片数据每行的长度是width*3。   
  46.              int skip_width = 0;   
  47.              int m = d.width * 3 % 4;   
  48.              if (m != 0) {   
  49.                  skip_width = 4 - m;   
  50.              }   
  51.       
  52.              // 通过遍历给数组填值   
  53.              // 这里需要注意,因为根据bmp的保存格式。   
  54.              // 位图数据中height的值如果是正数的话:   
  55.              // 那么数据就是按从下到上,从左到右的顺序来保存。这个称之为倒向位图。   
  56.              // 反之就是按从上到下,从左到右的顺序来保存。这个则称之为正向位图。   
  57.              for (int i = d.height - 1; i >= 0; i--) {   
  58.                  for (int j = 0; j < d.width; j++) {   
  59.                      try {   
  60.                          // 这里遍历的时候,一定要注意本来像素是有RGB来表示,   
  61.                          // 但是在存储的时候由于windows是小段存储,所以在内存中是BGR顺序。   
  62.                              d.blue[i][j] = bis.read();   
  63.                              d.green[i][j] = bis.read();   
  64.                              d.red[i][j] = bis.read();
  65.                         
  66.                         
  67.                          // 这里一定要知道,其实系统在给位图数据中添加填充0的时候,都是加在每行的最后。   
  68.                          // 但是我们在使用dis.skipBytes()这个方法的时候,却不一定要在最后一列。   
  69.                          // 系统在填充数据的时候,在数据上加了标记。   
  70.                          // 所以dis.skipBytes()这个方法只要调用了,那么系统就会自动不读取填充数据。   
  71.                          if (j == 0) {   
  72.                              bis.skip(skip_width);   
  73.                          }   
  74.                      } catch (IOException e) {   
  75.                          e.printStackTrace();   
  76.                      }
  77.                  }
  78.                  
  79.                  
  80.              }     
  81.    
  82.              fin.close();   
  83.              bis.close();   
  84.    
  85.              // 创建BMP对象来显示图画   
  86.                
  87.          } catch (Exception e) {   
  88.              e.printStackTrace();   
  89.          }   
  90.       
  91.    
  92.             return d;
  93.     }
  94.     public int ChangeInt(byte[] array2, int start) {   
  95.         // 因为char,byte,short这些数据类型经过运算符后会自动转为成int数据类,   
  96.         // 所以array2[start]&0xff的实际意思就是通过&0xff将字符数据转化为正int数据,然后在进行位运算。   
  97.         // 这里需要注意的是<<的优先级别比&高,所以必须加上括号。   
  98.   
  99.         int i = (int) ((array2[start] & 0xff) << 24)   
  100.                 | ((array2[start - 1] & 0xff) << 16)   
  101.                 | ((array2[start - 2] & 0xff) << 8)   
  102.                 | (array2[start - 3] & 0xff);   
  103.         return i;   
  104.     }   

  105. }
复制代码

作者: 刘俊佳    时间: 2012-7-16 13:45
我把byte[] buf=new byte[1024*1024];改成byte[] buf=new byte[1024*20];然后编译成功了,谢谢楼上几位的详细回答,最重要的是要我明白是怎么回事了
作者: 王宝康    时间: 2012-7-16 15:06
其实我感觉楼主这个程序就是实现了图片的复制粘贴操作,为了向新的目的地粘贴全部图片数据,所有要知道分割了多少份,所以分隔与合并共享一个成员变量count,分割后的数量传入合并函数中,进行合并操作,最终实现把图片从一个盘复制到另一盘的效果。
  1. package IOStudy;

  2. import java.io.*;
  3. import java.util.ArrayList;
  4. import java.util.Enumeration;

  5. public class SplitFile {

  6.         static int count = 1;
  7.         public static void main(String[] args) throws IOException {
  8.                 splitFile();
  9.                 merge();
  10.         }

  11.         public static void merge() throws IOException {
  12.                 ArrayList<FileInputStream> a1 = new ArrayList<FileInputStream>();
  13.                 System.out.print(count);

  14.                 for (int x = 1; x <= count-1; x++) {
  15.                         a1.add(new FileInputStream("D:\\test\\splitfiles\\" + x
  16.                                         + ".part"));
  17.                 }
  18.                 final java.util.Iterator<FileInputStream> it = a1.iterator();

  19.                 Enumeration<FileInputStream> en = new Enumeration<FileInputStream>() {
  20.                         public boolean hasMoreElements() {
  21.                                 return it.hasNext();
  22.                         }
  23.                         public FileInputStream nextElement() {
  24.                                 return it.next();
  25.                                 }
  26.                 };

  27.                 SequenceInputStream sis = new SequenceInputStream(en);
  28.                 FileOutputStream fos = new FileOutputStream(
  29.                                 "D:\\test\\splitfiles\\0.gif");
  30.                
  31.                 byte[] buf = new byte[1024 * 1024];
  32.                 int len = 0;
  33.                 while ((len = sis.read(buf)) != -1) {
  34.                         fos.write(buf, 0, len);
  35.                 }
  36.                 fos.close();
  37.                 sis.close();

  38.         }

  39.         public static void splitFile() throws IOException {
  40.                 FileInputStream fis = new FileInputStream("d:\\1.gif");

  41.                 FileOutputStream fos = null;

  42.                 byte[] buf = new byte[20* 20];

  43.                 int len = 0;
  44.                 while ((len = fis.read(buf)) != -1) {

  45.                         fos = new FileOutputStream("D:\\test\\splitfiles\\" + (++count)
  46.                                         + ".part");
  47.                         fos.write(buf, 0, len);
  48.                         fos.close();
  49.                 }
  50.                 System.out.println(count);
  51.                 fis.close();

  52.         }
  53. }
复制代码





欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2