2010-12-13 19 views
16

Próbuję podzielić plik binarny (np. Wideo/audio/obraz) na porcje o wielkości 100 kb każdy, a następnie połączyć te fragmenty, aby odzyskać oryginalny plik. Mój kod wydaje się działać, w tym sensie, że dzieli plik i łączy się z kawałkami, plik, który otrzymuję, ma ten sam rozmiar co oryginał. Problem polega jednak na tym, że zawartość zostaje obcięta - to znaczy, jeśli jest to plik wideo, zatrzymuje się po 2 sekundach, jeśli jest to plik obrazu, to tylko górna część wygląda poprawnie.Podziel i dołącz plik binarny do java

Oto kod używam (mogę pisać cały kod, jeśli chcesz):

do podziału:

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; 

A do łączenia plików, umieścić nazwiska wszystkich kawałków w List, a następnie posortować je według nazwy, a następnie uruchom następujący kod:

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; 

Odpowiedz

10

mogę dostrzec tylko 2 potencjalne błędy w kodzie:

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

Powyższy zawodzi, gdy plik ma ponad 2 GB, ponieważ int nie może pomieścić więcej.

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

Tak skonstruowaną nazwę pliku należy posortować w bardzo specyficzny sposób. Podczas korzystania z domyślnego sortowania ciągów, name.part10 pojawi się przed name.part2.Chciałbyś dostarczyć niestandardowy Comparator, który wyodrębnia i parsuje numer części jako int, a następnie porównuje przez to.

+0

Plik jest znacznie mniejszy niż 2 GB - ale masz rację co do części sortującej, zajmuje ona 0,1,10,11,12 ..., 2,20 itd. - Zgaduję, że to zepsuje –

+0

To działa! Wielkie dzięki! –

+0

Nie ma za co. – BalusC

0

Co się dzieje, kiedy zrobić binarne porównywanie plików. na przykład z różnicą. Czy widzisz różnicę po pierwszym pliku?

Czy możesz spróbować zepsuć tekstowy plik TXT? jeśli są bajty są nie na miejscu, powinno być bardziej oczywiste, co idzie źle. na przykład powtórzony blok/plik/lub dane pełne zerowych bajtów. ??

EDYCJA: Jak inni zauważyli, czytasz pliki w określonej kolejności. Możesz użyć wyściełanego numeru pliku, takiego jak.

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

Daje to do 1 miliarda plików w porządku numerycznym.

Po przeczytaniu plików należy się upewnić, że są one posortowane.

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

Używanie niestandardowej porównawczy jak inni sugerują, że zmniejszenie wielkości wyściełane liczb, ale może być miło móc sortować według nazwy, aby uzyskać prawidłową kolejność. na przykład w eksploratorze.

+0

Tylko drobna korekta: powinieneś zamienić ".part" w formacie z "% s" lub usunąć parametr ".part". –

+0

@ Serio, dziękuję za ten punkt. –

3

A do łączenia plików, umieścić nazwiska wszystkich fragmentów w formie listy, a następnie posortować je według nazwy, a następnie uruchom następujący kod:

Ale wasze imiona są w następującej postaci:

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

Zastanów się dobrze, co się stanie, jeśli masz 11 lub więcej części. Który ciąg jest pierwszy w kolejności alfabetycznej: ".part10" lub ".part2"? (Odpowiedź:”.part10" , od«1»jest przed«2»w kodowaniu znaków.)

+0

To działa! Wielkie dzięki! –

1

Czy jest więcej niż 10 kawałków? Następnie program połączy * .part1 + * .part10 + * .part2 i tak dalej.

+0

Wielkie dzięki! Naprawdę doceniam twoją pomoc! –

1

do dzielenia pliku: ----->

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

to ma wielkość podzielić nazwę pliku & docelowy (w bajcie) użytkownik forma i podzielić ją na podteksty jego pracy dla wszystkich typów plików, takich jak (.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"); }} 

i inny program scali wszystkie split files.It wziąć tylko podziału nazwę pliku i scalić wszystkie pliki.

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

powinieneś sformatować swój kod nieco lepiej – AbcAeffchen

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

Pożycz Closerhere lub from org.apache.logging.log4j.core.util.