2010-12-13 129 views
16

我想將二進制文件(如視頻/音頻/圖像)分成100kb的塊,然後再加入這些塊以獲取原始文件。 我的代碼似乎在工作,從它分割文件並加入塊的意義上說,我找回的文件與原始文件大小相同。然而,問題在於內容被截斷 - 也就是說,如果它是一個視頻文件,它會在2秒後停止,如果它是圖像文件,則只有上半部分看起來是正確的。在java中分割並回傳一個二進制文件

這裏是我使用(如果你願意,我可以張貼整個代碼)的代碼:

對於劃分:

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; 

而對於加盟的文件,我把所有的塊的名稱中列表,然後按名稱對其進行排序,然後運行以下代碼:

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; 

回答

10

我可以在代碼發現只有2個潛在的錯誤:

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

上面失敗時文件超過2GB,因爲int無法保存更多文件。

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

這樣構造的文件名應該以非常特定的方式排序。當使用默認字符串排序時,name.part10將會在name.part2之前出現。您想提供一個自定義Comparator,它提取並解析零件編號爲int,然後通過它進行比較。

+0

該文件遠遠少於2 GB - 但你是正確的排序部分,它採取0,1,10,11,12 ...,2,20等 - 我想這是搞砸了 – 2010-12-13 18:30:06

+0

這工作!非常感謝! – 2010-12-13 22:43:14

+0

不客氣。 – BalusC 2010-12-13 22:43:45

0

當您執行文件的二進制比較時會發生什麼情況。例如與差異。你在第一個文件後看到了差異嗎?

你可以試着分手一個文本TXT文件嗎?如果字節不合適,應該更明顯地發生什麼問題。例如一個重複的塊/文件/或數據完整的nul字節。 ??

編輯:正如其他人已經注意到,你讀的文件沒有特定的順序。你可以做的是使用填充的文件編號。

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

這會給你多達10億個文件的數字順序。

當您閱讀文件時,您需要確保它們已排序。

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

使用自定義比較像其他人那樣認爲會降低填充數字的大小,但它可以很高興能夠以按名稱排序,以得到正確的次序。例如在探險家。

+0

只需稍加修改:您應該將格式中的「.part」替換爲「%s」或刪除「.part」參數。 – 2010-12-13 19:41:32

+0

@Sergey,謝謝你的提示。 – 2010-12-13 21:03:30

3

而對於加盟的文件,我把所有的塊的名字在一個列表,然後按名稱排序,然後運行下面的代碼:

但你的名字有以下幾種形式:

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

仔細想想如果您有11個或更多零件會發生什麼。哪個字符串按字母順序排在第一位:「.part10」或「.part2」? (答案:」 .part10" 時,由於‘1’到來之前‘2’中的字符編碼。)

+0

這個工程!非常感謝! – 2010-12-13 22:43:37

1

是否有超過10塊?然後程序將連接* .part1 + * .part10 + * .part2等。

+0

非常感謝!非常感謝您的幫助! – 2010-12-13 22:43:58

1

對於拆分文件:----->

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(); 

} 

} 
0

它需要分割的文件名&目標文件大小(以字節)形式的用戶,併爲子文件的工作像所有類型的文件把它分解(.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<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"); }} 

和另一個程序將合併所有分割files.It只需要分割的文件名和合並的所有文件。

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){} }} 
+0

你應該更好地格式化你的代碼 – AbcAeffchen 2015-02-25 04:22:19

0
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; 
    } 
} 

Closerherefrom org.apache.logging.log4j.core.util