Mega Code Archive

 
Categories / Delphi / Files
 

File Splitter

Title: File Splitter Question: Split and join large files Answer: Many of us experience this incontrovertible need to slice large files into smaller pieces - the foll piece of code helps do just that - you can split large files into smaller pieces,(port/upload them..) and re-join them later. The crux of the file-splitter is the function, PERFORMSPLIT : procedure PerformSplit(const srcFn , dstDir: String; numSlices : Integer); var dstFl ,batCmd, tmpFn : String; srcFStrm : TFileStream; strmSize , destFlSize , modRes : LongInt; cntSlice : Integer; accom : boolean; begin {0} { srcFn - File to split dstDir - directory that 'll hold the file slices and the .BAT file that joins them numSlices - number of slices } accom := false; {the flag above ('accom') is used when the source file cannot be accomodated wholly in the no. of slices specified, i.e., if the last piece needs to contain lesser data - we could have done without this flag, computing the space size of each slice on the fly, but this makes the code look just a little easier } srcFStrm := TFileStream.create(srcFn,fmOpenRead); strmSize := srcFStrm.size; destFlsize := strmSize div numSlices; modRes := strmsize mod numSlices; if (modRes) 0 then {1} begin dec(numSlices); accom := true; end; {1} srcFStrm.position := 0; try {2} cntslice := 1; tmpFn := extractfilename(changefileext(srcFn,'')); Application.ProcessMessages; while cntslice begin {3} dstFl := tmpFn+'_$_'+inttostr(cntslice); {batCmd - contains the DOS 'Copy' command that 'll be executed by the .bat file to join the file slices} batCmd := batCmd + dstFl + '+'; dstFl := IncludeTrailingPathDelimiter(dstDir)+dstFl; strmcopy(dstFl,srcFStrm,destFlSize); inc(cntslice); end; {3} if accom then // 1 slice left begin {4} inc(destFlSize,modRes); dstFl := tmpFn+'_$_'+inttostr(cntslice); batCmd := batCmd + dstFl +'+'; dstFl := IncludeTrailingPathDelimiter(dstDir)+dstFl; strmcopy(dstFl,srcFStrm,destFlSize); end; {4} setLength(batCmd,length(batCmd)-1); batCmd := 'COPY /B '+ batCmd + ' '+extractfilename(srcFn); generateBatFile(dstDir,extractfilename(changefileext(srcFn,''))+'_$_.bat', batCmd); finally srcFStrm.free; end; {2} end; {0} {the foll proc saves the slices to the destination directory } procedure StrmCopy(const destFl : String;const srcFStrm : TFileStream;destFlSize : longInt); var dstFStrm : TFileStream; begin dstFStrm := TFileStream.create(destfl,fmCreate); try dstFstrm.CopyFrom(srcFStrm,destFlSize); finally dstFStrm.free; end; end; {the foll proc creates a DOS-Batch(.bat) file that re-joins the file slices to obtain the original file, provided the file slices and the .bat file are in the same folder} procedure generateBatFile(const dstDir , batName, batCmd : String); var batFl : TextFile; dstBAT : String; begin dstBAT := IncludeTrailingPathDelimiter(dstDir)+batName; assignfile(batFl,dstBAT); rewrite(batFl); writeln(batFl,'rem Auth : Prashant Gulati'); writeln(batFl,batCmd); closefile(batFl); end; Note : 1) The above program,in its present form,would not be able to regenerate the source files that have spaces in their names. Nonetheless, an easy work-around is not a problem 2) When executing the batch file make sure that the file slices and the .bat are in the same directory 3) If you find execution using .bat files slow, you could write a small module that would regenerate the file using the same approach (file streams) as discussed above Please rate this article if you liked it :) Affly Prashant Gulati