拆分并加入java中的二进制文件

我试图将二进制文件(如video/音频/图像)分成每个100kb的块,然后将这些块连接起来以取回原始文件。 我的代码似乎正在工作,在它分割文件并加入块的意义上,我得到的文件与原始文件大小相同。 然而,问题是内容被截断 – 也就是说,如果它是一个video文件,它会在2秒后停止,如果它是图像文件,那么只有上半部分看起来正确。

这是我正在使用的代码(如果你愿意,我可以发布整个代码):

划分:

File ifile = new File(fname); FileInputStream fis; String newName; FileOutputStream chunk; int fileSize = (int) ifile.length(); int nChunks = 0, read = 0, readLength = Chunk_Size; byte[] byteChunk; try { fis = new FileInputStream(ifile); StupidTest.size = (int)ifile.length(); while (fileSize > 0) { if (fileSize <= Chunk_Size) { readLength = fileSize; } byteChunk = new byte[readLength]; read = fis.read(byteChunk, 0, readLength); fileSize -= read; assert(read==byteChunk.length); nChunks++; newName = fname + ".part" + Integer.toString(nChunks - 1); chunk = new FileOutputStream(new File(newName)); chunk.write(byteChunk); chunk.flush(); chunk.close(); byteChunk = null; chunk = null; } fis.close(); fis = null; 

为了加入文件,我将所有块的名称放在List中,然后按名称对其进行排序,然后运行以下代码:

 File ofile = new File(fname); FileOutputStream fos; FileInputStream fis; byte[] fileBytes; int bytesRead = 0; try { fos = new FileOutputStream(ofile,true); for (File file : files) { fis = new FileInputStream(file); fileBytes = new byte[(int) file.length()]; bytesRead = fis.read(fileBytes, 0,(int) file.length()); assert(bytesRead == fileBytes.length); assert(bytesRead == (int) file.length()); fos.write(fileBytes); fos.flush(); fileBytes = null; fis.close(); fis = null; } fos.close(); fos = null; 

我只能在代码中发现2个潜在的错误:

 int fileSize = (int) ifile.length(); 

当文件超过2GB时,上述操作失败,因为int无法容纳更多文件。

 newName = fname + ".part" + Integer.toString(nChunks - 1); 

像这样构造的文件名应该以非常具体的方式排序。 使用默认字符串排序时, name.part10name.part2之前。 您想提供一个自定义Comparator ,它将部件号提取并解析为int,然后进行比较。

为了加入文件,我将所有块的名称放在List中,然后按名称对其进行排序,然后运行以下代码:

但是你的名字是以下forms:

 newName = fname + ".part" + Integer.toString(nChunks - 1); 

仔细考虑如果您有11个或更多部件会发生什么。 哪个字符串按字母顺序排在第一位:“。part10”或“.part2”? (答案:“。part10”,因为’1’在字符编码中位于’2’之前。)

有超过10个块吗? 然后程序将连接* .part1 + * .part10 + * .part2,依此类推。

分割文件:—–>

 import java.io.*; class Split { public static void main(String args[])throws IOException { Console con=System.console(); System.out.println("enter the file name"); String path=con.readLine(); File f= new File(path); int filesize=(int)f.length(); FileInputStream fis= new FileInputStream(path); int size; System.out.println("enter file size for split"); size=Integer.parseInt(con.readLine()); byte b[]=new byte[size]; int ch,c=0; while(filesize>0) { ch=fis.read(b,0,size); filesize = filesize-ch; String fname=c+"."+f.getName()+""; c++; FileOutputStream fos= new FileOutputStream(new File(fname)); fos.write(b,0,ch); fos.flush(); fos.close(); } fis.close(); } } 

当您对文件进行二进制比较时会发生什么。 例如,差异 你看到第一个文件后有什么不同吗?

你能尝试分解文本TXT文件吗? 如果有字节不合适,那么出错的原因应该更明显。 例如,重复的块/文件/或充满nul字节的数据。 ??

编辑:正如其他人注意到的那样,您没有按特定顺序阅读文件。 您可以做的是使用填充的文件编号。

 newName = String.format("%s.part%09d", fname, nChunks - 1); 

这将按数字顺序为您提供多达10亿个文件。

阅读文件时,需要确保它们已排序。

 Arrays.sort(files); for (File file : files) { 

使用其他人建议的自定义比较器会减少填充数字的大小,但能够按名称排序以获得正确的顺序可能会很好。 例如在探险家。

它采用分割文件名和目标文件大小(以字节为单位)forms的用户并将其拆分为子文件,它适用于所有类型的文件,如(.bin,.jpg,.rar)

 import java.io.*; class split{ public static void main(String args[])throws IOException { String a; int b; long len; Console con=System.console(); System.out.println("Enter File Name: "); File f=new File(con.readLine()); System.out.println("Enter Destination File Size: "); b=Integer.parseInt(con.readLine()); FileInputStream fis=new FileInputStream(f); len=f.length(); int c=(int)len/b; if(((int)len%b)!=0) c++; for(int i=0;i 

另一个程序将合并所有拆分文件。它只采用拆分文件名并合并所有文件。

 import java.io.*; class merge{ static int i; public static void main(String args[])throws IOException{ String a; int b; long len; Console con=System.console(); System.out.println("Enter File to be retrived: "); File f=new File(con.readLine()); FileOutputStream fos=new FileOutputStream(f,true); try { File f1=new File(i+""+"."+f); while((f1.exists())!=false) { int ch; FileInputStream fis=new FileInputStream(i+""+"."+f); i++; while((ch=fis.read())!=-1){ fos.write(ch); }}} catch(FileNotFoundException e1){} }} 
 public class FileSplitter { private static final int BUFSIZE = 4*1024; public boolean needsSplitting(String file, int chunkSize) { return new File(file).length() > chunkSize; } private static boolean isASplitFileChunk(String file) { return chunkIndexLen(file) > 0; } private static int chunkIndexLen(String file) { int n = numberOfTrailingDigits(file); if (n > 0) { String zeroes = new String(new char[n]).replace("\0", "0"); if (file.matches(".*\\.part[0-9]{"+n+"}?of[0-9]{"+n+"}?$") && !file.endsWith(zeroes) && !chunkNumberStr(file, n).equals(zeroes)) { return n; } } return 0; } private static String getWholeFileName(String chunkName) { int n = chunkIndexLen(chunkName); if (n>0) { return chunkName.substring(0, chunkName.length() - 7 - 2*n); // 7+2n: 1+4+n+2+n : .part012of345 } return chunkName; } private static int getNumberOfChunks(String filename) { int n = chunkIndexLen(filename); if (n > 0) { try { String digits = chunksTotalStr(filename, n); return Integer.parseInt(digits); } catch (NumberFormatException x) { // should never happen } } return 1; } private static int getChunkNumber(String filename) { int n = chunkIndexLen(filename); if (n > 0) { try { // filename.part001of200 String digits = chunkNumberStr(filename, n); return Integer.parseInt(digits)-1; } catch (NumberFormatException x) { } } return 0; } private static int numberOfTrailingDigits(String s) { int n=0, l=s.length()-1; while (l>=0 && Character.isDigit(s.charAt(l))) { n++; l--; } return n; } private static String chunksTotalStr(String filename, int chunkIndexLen) { return filename.substring(filename.length()-chunkIndexLen); } protected static String chunkNumberStr(String filename, int chunkIndexLen) { int p = filename.length() - 2 - 2*chunkIndexLen; // 123of456 return filename.substring(p,p+chunkIndexLen); } // 0,8 ==> part1of8; 7,8 ==> part8of8 private static String chunkFileName(String filename, int n, int total, int chunkIndexLength) { return filename+String.format(".part%0"+chunkIndexLength+"dof%0"+chunkIndexLength+"d", n+1, total); } public static String[] splitFile(String fname, long chunkSize) throws IOException { FileInputStream fis = null; ArrayList res = new ArrayList(); byte[] buffer = new byte[BUFSIZE]; try { long totalSize = new File(fname).length(); int nChunks = (int) ((totalSize + chunkSize - 1) / chunkSize); int chunkIndexLength = String.format("%d", nChunks).length(); fis = new FileInputStream(fname); long written = 0; for (int i=0; written0) { int nChunks = getNumberOfChunks(chunkName); String filename = getWholeFileName(chunkName); for (int i=0; i0) { int nChunks = getNumberOfChunks(chunkName); String filename = getWholeFileName(chunkName); byte[] buffer = new byte[BUFSIZE]; FileOutputStream fos = new FileOutputStream(filename); try { for (int i=0; i0) { int nChunks = getNumberOfChunks(chunkName); String filename = getWholeFileName(chunkName); for (int i=0; i 

在这里或从org.apache.logging.log4j.core.util借用Closer