在Java中将.gz文件拆分为指定的文件大小

时间:2012-03-13 07:02:35

标签: java split gzip

这是我的第一篇帖子,所以不确定我对这个问题的描述是多么恰当..

下面是我编写的一个程序,用于根据用户想要的每个文件的大小将.gz文件拆分成文件。父.gz文件正在拆分,但不会达到代码中指定的大小。 例如,在主要我说过我希望将父文件拆分为大小为1 MB的文件。但是在执行代码时,它会分成n个不同大小的文件。有人可以帮我指出我错的地方吗?任何帮助都会很棒,因为我的想法已经用完了......

package com.bitsighttech.collection.packaging;  


import java.io.BufferedReader;  
import java.io.DataInputStream;  
import java.io.File;  
import java.io.FileInputStream;  
import java.io.FileOutputStream;  
import java.io.InputStreamReader;  
import java.util.ArrayList;  
import java.util.List;  
import java.util.regex.Matcher;  
import java.util.regex.Pattern;  
import java.util.zip.GZIPInputStream;  
import java.util.zip.GZIPOutputStream;  

import org.apache.log4j.Logger;  

public class FileSplitter   
{  
    private static Logger logger = Logger.getLogger(FileSplitter.class);  
    private static final long KB = 1024;  
    private static final long MB = KB * KB;        

    public List<File> split(File inputFile, String splitSize)    
    {    
        int expectedNoOfFiles =0;         
        List<File> splitFileList = new ArrayList<File>();  
        try    
        {    
            double parentFileSizeInB = inputFile.length();  
            Pattern p = Pattern.compile("(\\d+)\\s([MmGgKk][Bb])");  
            Matcher m = p.matcher(splitSize);  
            m.matches();  
            String FileSizeString = m.group(1);  
            System.out.println("FileSizeString----------------------"+FileSizeString);  
            String unit = m.group(2);  
            double fileSizeInMB = 0;  

            try {  
                if (unit.toLowerCase().equals("kb"))  
                    fileSizeInMB = Double.parseDouble(FileSizeString) / KB;           
                else if (unit.toLowerCase().equals("mb"))  
                    fileSizeInMB = Double.parseDouble(FileSizeString);                
                else if (unit.toLowerCase().equals("gb"))  
                    fileSizeInMB = Double.parseDouble(FileSizeString) * KB;           
            }   
            catch (NumberFormatException e) {  
                logger.error("invalid number [" + fileSizeInMB  + "] for expected file size");  
            }             
            System.out.println("fileSizeInMB----------------------"+fileSizeInMB);  
            double fileSize = fileSizeInMB * MB;  
            long fileSizeInByte = (long) Math.ceil(fileSize);  
            double noOFFiles = parentFileSizeInB/fileSizeInByte;   
            expectedNoOfFiles =  (int) Math.ceil(noOFFiles);  
            System.out.println("0000000000000000000000000"+expectedNoOfFiles);  
            GZIPInputStream in = new GZIPInputStream(new FileInputStream(inputFile));             
            DataInputStream datain = new DataInputStream(in);  
            BufferedReader fis = new BufferedReader(new InputStreamReader(datain));  
            int count= 0 ;  
            int splinterCount = 1;  
            GZIPOutputStream outputFileWriter = null;  
            while ((count = fis.read()) != -1)   
            {  
                System.out.println("count----------------------1 "+count);  
                int outputFileLength = 0;    
                outputFileWriter = new  GZIPOutputStream(new FileOutputStream("F:\\ff\\" + "_part_" + splinterCount + "_of_" + expectedNoOfFiles + ".gz"));  
                while (     (count = fis.read()) != -1   
                        &&  outputFileLength < fileSizeInByte  
                ) {    

                    outputFileWriter.write(count);    
                    outputFileLength ++;    
                    count = fis.read();  

                }  
                System.out.println("count----------------------2 "+count);  
                //outputFileWriter.finish();  
                outputFileWriter.close();  
                splinterCount ++;    
            }  
            fis.close();  
            datain.close();  
            in.close();  
            outputFileWriter.close();  
            System.out.println("Finished");  

        }catch(Exception e)    
        {    
            logger.error("Unable to split the file " + inputFile.getName() + " in to " + expectedNoOfFiles);  
            return null;  
        }    
        logger.debug("Successfully split the file [" + inputFile.getName() + "] in to " + expectedNoOfFiles + " files");  
        return splitFileList;  
    }      

    public static void main(String args[])   
    {  
        String filePath1 = "F:\\filename.gz";  
        File  file = new File(filePath1);  

        FileSplitter fileSplitter = new FileSplitter();  
        String splitlen = "1 MB";  
        int noOfFilesSplit = 3;  

        fileSplitter.split(file, splitlen);  

    }  
}  

3 个答案:

答案 0 :(得分:1)

Andreas的回答涵盖了您的主要问题,但该代码中存在很多问题。最重要的是,你为每个'split'抛出一个字节(外部while调用fis.read()并忽略该值)。

如果你一次只读取一个字节,为什么要将gzip输入流包装在DataInputStream BufferedReader中?

编辑

啊,你也扔掉了每个分裂的最后字节(除了最后一个)。

答案 1 :(得分:0)

很难说,但它看起来像是在计算未压缩的字节数。压缩块(结果文件)将更小。

答案 2 :(得分:0)

使用gzip压缩数据时,输出文件大小取决于数据的复杂程度。在这里,您正在压缩相同大小的块,但它们的压缩大小是不同的。没有无损压缩算法可以通过常数因子减小输入的大小。

如果你想要相同大小的碎片,你应该拆分压缩数据而不是先解压缩。但这当然意味着碎片必须按顺序解压缩,如果不读取碎片,就不能解压缩碎片。