这是我的第一篇帖子,所以不确定我对这个问题的描述是多么恰当..
下面是我编写的一个程序,用于根据用户想要的每个文件的大小将.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);
}
}
答案 0 :(得分:1)
Andreas的回答涵盖了您的主要问题,但该代码中存在很多问题。最重要的是,你为每个'split'抛出一个字节(外部while
调用fis.read()并忽略该值)。
如果你一次只读取一个字节,为什么要将gzip输入流包装在DataInputStream 和 BufferedReader中?
编辑啊,你也扔掉了每个分裂的最后字节(除了最后一个)。
答案 1 :(得分:0)
很难说,但它看起来像是在计算未压缩的字节数。压缩块(结果文件)将更小。
答案 2 :(得分:0)
使用gzip压缩数据时,输出文件大小取决于数据的复杂程度。在这里,您正在压缩相同大小的块,但它们的压缩大小是不同的。没有无损压缩算法可以通过常数因子减小输入的大小。
如果你想要相同大小的碎片,你应该拆分压缩数据而不是先解压缩。但这当然意味着碎片必须按顺序解压缩,如果不读取碎片,就不能解压缩碎片。