在java中拆分并连接回二进制文件

在java中拆分并连接回二进制文件,java,file-io,Java,File Io,我正在尝试将一个二进制文件(如视频/音频/图像)划分为每个100kb的块,然后将这些块合并回原始文件。 我的代码似乎在工作,从它分割文件并连接块的意义上讲,我得到的文件与原始文件的大小相同。然而,问题是内容被截断了——也就是说,如果是视频文件,它会在2秒钟后停止,如果是图像文件,那么只有上面的部分看起来是正确的 以下是我正在使用的代码(如果您愿意,我可以发布整个代码): 用于划分: File ifile = new File(fname); FileInputStream fis; Strin

我正在尝试将一个二进制文件(如视频/音频/图像)划分为每个100kb的块,然后将这些块合并回原始文件。 我的代码似乎在工作,从它分割文件并连接块的意义上讲,我得到的文件与原始文件的大小相同。然而,问题是内容被截断了——也就是说,如果是视频文件,它会在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;

对文件进行二进制比较时会发生什么情况。e、 g.有差异。第一个文件之后,您是否看到差异

你能试着分解一个文本TXT文件吗?如果有字节不在适当的位置,那么应该更清楚地知道哪里出了问题。e、 g.一个重复的块/文件/或充满nul字节的数据

编辑:正如其他人所注意到的,您没有按特定顺序读取文件。您可以使用一个填充的文件号,如

newName = String.format("%s.part%09d", fname, nChunks - 1);
这将以数字顺序为您提供多达10亿个文件

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

Arrays.sort(files);
for (File file : files) {
正如其他人所建议的那样,使用自定义比较器可以减少填充数字的大小,但是能够按名称排序以获得正确的顺序是很好的。e、 在探险家中

为了连接文件,我将所有块的名称放在一个列表中,然后按名称排序,然后运行以下代码:

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;
但您的姓名如下:

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

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

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

int fileSize = (int) ifile.length();
当文件超过2GB时,上述操作失败,因为
int
不能容纳更多文件

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

这样构造的文件名应该以非常特定的方式进行排序。使用默认字符串排序时,
name.part10
将位于
name.part2
之前。您希望提供一个自定义的方法,将零件号提取并解析为int,然后用int进行比较。

是否有10个以上的块?然后程序将连接*.part1+*.part10+*.part2,依此类推。

用于拆分文件:-->


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

公共类文件剥离器{
私有静态final int BUFSIZE=4*1024;
公共布尔值需要拆分(字符串文件,int chunkSize){
返回新文件(File).length()>chunkSize;
}
私有静态布尔isASplitFileChunk(字符串文件){
返回chunkIndexLen(文件)>0;
}
私有静态int chunkIndexLen(字符串文件){
int n=跟踪数字(文件)的数量;
如果(n>0){
字符串零=新字符串(新字符[n])。替换(“\0”,“0”);
如果(file.matches(“.\\\.部分[0-9]{“+n+”}?$”)&&!file.endsWith(零)和&!chunkNumberStr(file,n).equals(零)){
返回n;
}
}
返回0;
}
私有静态字符串getWholeFileName(字符串chunkName){
int n=chunkIndexLen(chunkName);
如果(n>0){
返回chunkName.substring(0,chunkName.length()-7-2*n);//7+2n:1+4+n+2+n:.part012of345
}
返回chunkName;
}
私有静态int getNumberOfChunks(字符串文件名){
int n=chunkIndexLen(文件名);
如果(n>0){
试一试{
字符串数字=chunksTotalStr(文件名,n);
返回整数.parseInt(位数);
}catch(NumberFormatException){//永远不会发生
}
}
返回1;
}
私有静态int getChunkNumber(字符串文件名){
int n=chunkIndexLen(文件名);
如果(n>0){
试一试{
//filename.part001of200
字符串数字=chunkNumberStr(文件名,n);
返回整数.parseInt(位数)-1;
}捕获(NumberFormatException x){
}
}
返回0;
}
私有静态int numberOfTrailingDigits(字符串s){
int n=0,l=s.length()-1;
而(l>=0&&Character.isDigit(s.charAt(l))){
n++;l--;
}
返回n;
}
私有静态字符串chunksTotalStr(字符串文件名,int chunkIndexLen){
返回filename.substring(filename.length()-chunkIndexLen);
}
受保护的静态字符串chunkNumberStr(字符串文件名,int chunkIndexLen){
int p=filename.length()-2-2*chunkIndexLen;//123of456
返回filename.substring(p,p+chunkIndexLen);
}
//0,8==>part1of8;7,8==>part8of8
私有静态字符串chunkFileName(字符串文件名,int n,int total,int chunkIndexLength){
返回文件名+字符串.format(“.part%0”+chunkIndexLength+“dof%0”+chunkIndexLength+“d”,n+1,总计);
}
公共静态字符串[]拆分文件(字符串fname,长chunkSize)引发IOException{
FileInputStream fis=null;
ArrayList res=新的ArrayList();
字节[]缓冲区=新字节[BUFSIZE];
试一试{
long totalSize=新文件(fname).length();
int nChunks=(int)((totalSize+chunkSize-1)/chunkSize);
int chunkIndexLength=String.format(“%d”,nChunks).length();
fis=新文件输入流(fname);
长写=0;
for(int i=0;writen0){
int nChunks=getNumberOfChunks(chunkName);
字符串文件名=getWholeFileName(chunkName);
对于(int i=0;i0){
int nChunks=getNumberOfChunks(chunkName);
字符串文件名=getWholeFileName(chunkName);
字节[]缓冲区=新字节[BUFSIZE];
FileOutputStream fo
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();

}

}
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<c;i++){
File f1=new File(i+""+"."+f);
FileOutputStream fos=new FileOutputStream(f1);
for(int j=0;j<b;j++){   
int ch;
if((ch=fis.read())!=-1)
fos.write(ch); } }
fis.close();
System.out.println("Operation Successful"); }}
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<String> res = new ArrayList<String>();
        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; written<totalSize; i++) {
                String chunkFName = chunkFileName(fname, i, nChunks, chunkIndexLength);
                FileOutputStream fos = new FileOutputStream(chunkFName);
                try {
                    written += copyStream(fis, buffer, fos, chunkSize);
                } finally {
                    Closer.closeSilently(fos);
                }
                res.add(chunkFName);
            }
        } finally {
            Closer.closeSilently(fis);
        }
        return res.toArray(new String[0]);
    }
    public static boolean canJoinFile(String chunkName) {
        int n = chunkIndexLen(chunkName);
        if (n>0) {
            int nChunks = getNumberOfChunks(chunkName);
            String filename = getWholeFileName(chunkName);
            for (int i=0; i<nChunks; i++) {
                if (!new File(chunkFileName(filename, i, nChunks, n)).exists()) {
                    return false;
                }
            }
            return true;
        }
        return false;
    }
    public static void joinChunks(String chunkName) throws IOException {
        int n = chunkIndexLen(chunkName);
        if (n>0) {
            int nChunks = getNumberOfChunks(chunkName);
            String filename = getWholeFileName(chunkName);
            byte[] buffer = new byte[BUFSIZE];
            FileOutputStream fos = new FileOutputStream(filename);
            try {
                for (int i=0; i<nChunks; i++) {
                    FileInputStream fis = new FileInputStream(chunkFileName(filename, i, nChunks, n));
                    try {
                        copyStream(fis, buffer, fos, -1);
                    } finally {
                        Closer.closeSilently(fis);
                    }
                }
            } finally {
                Closer.closeSilently(fos);
            }
        }
    }
    public static boolean deleteAllChunks(String chunkName) {
        boolean res = true;
        int n = chunkIndexLen(chunkName);
        if (n>0) {
            int nChunks = getNumberOfChunks(chunkName);
            String filename = getWholeFileName(chunkName);
            for (int i=0; i<nChunks; i++) {
                File f = new File(chunkFileName(filename, i, nChunks, n));
                res &= (f.delete() || !f.exists());
            }
        }
        return res;
    }
    private static long copyStream(FileInputStream fis, byte[] buffer, FileOutputStream fos, long maxAmount) throws IOException {
        long chunkSizeWritten;
        for (chunkSizeWritten=0; chunkSizeWritten<maxAmount || maxAmount<0; ) {
            int toRead = maxAmount < 0 ? buffer.length : (int)Math.min(buffer.length, maxAmount - chunkSizeWritten);
            int lengthRead = fis.read(buffer, 0, toRead);
            if (lengthRead < 0) {
                break;
            }
            fos.write(buffer, 0, lengthRead);
            chunkSizeWritten += lengthRead;
        }
        return chunkSizeWritten;
    }
}