Home page > Delphi, tips bulk > Miscellaneous > CopyStreamFileSegment: copying segments of streams or files

CopyStreamFileSegment: copying segments of streams or files

Sunday 18 September 2011, by CapJack

This unit is used to copy segments of streams/files, or in a destination open stream/file, which content will be modified, or in a new file.

Compatible with Delphi/Lazarus all versions, all platforms.

I’m not asking anything in return for this work, except a small link to my site if you find it useful and use it in your software.

CapJack.

  1. (*********************************************************)
  2. (***)                                                 (***)
  3. (***)          UNIT CopyStreamFileSegment;            (***)
  4. (***)                                                 (***)
  5. (*********************************************************)
  6.  
  7. (*********************************************************)
  8. (* Feel free to use it, but at your own risk!            *)
  9. (* À utiliser librement, mais à vos risques et périls !  *)
  10. (* CapJack.                                              *)
  11. (*********************************************************)
  12.  
  13.  
  14. (*********************************************************)
  15. (***)                                                 (***)
  16. (***)                  INTERFACE                      (***)
  17. (***)                                                 (***)
  18. (*********************************************************)
  19.  
  20. uses Classes;
  21.  
  22.  
  23. const     CSFSDefBufSize = 64*1024;
  24.  
  25. type      CSFSFileProgress
  26.            = procedure(const Pos:Int64) of object;
  27.  
  28. (*********************************************************)
  29. (* DTCopyStreamSegment                                   *)
  30. (* ----------------------------------------------------- *)
  31. (* Copy a segment of stream in another stream            *)
  32. (* AStream1     : source stream                          *)
  33. (* AnOffset1    : offset of data to copy                 *)
  34. (* AStream2     : destination stream                     *)
  35. (* AnOffset2    : destination address                    *)
  36. (* ALength      : length to copy (zero -> maximum)       *)
  37. (* AnOnProgress : progress callback event                *)
  38. (* ABufferSize  : buffer size to use                     *)
  39. (* ----------------------------------------------------- *)
  40. (* Copie un segment de flux dans un autre flux           *)
  41. (* AStream1     : flux source                            *)
  42. (* AnOffset1    : adresse des données à copier           *)
  43. (* AStream2     : flux de destination                    *)
  44. (* AnOffset2    : adresse de destination                 *)
  45. (* ALength      : longueur à copier  (zéro -> maximum)   *)
  46. (* AnOnProgress : évènement de progression en retour     *)
  47. (* ABufferSize  : taille de buffer à utiliser            *)
  48. (*********************************************************)
  49.  
  50. procedure DTCopyStreamSegment
  51.         (
  52.         const AStream1          : TStream;
  53.         const AnOffset1         : Int64;
  54.         const AStream2          : TStream;
  55.         const AnOffset2         : Int64;
  56.         const ALength           : Int64;
  57.         const AnOnProgress      : CSFSFileProgress = nil;
  58.         const ABufferSize       : Int64 = CSFSDefBufSize
  59.         );
  60.  
  61. (*********************************************************)
  62. (* DTCopyFileSegment                                     *)
  63. (* ----------------------------------------------------- *)
  64. (* Copy a segment of file in another file                *)
  65. (* AFileName1   : source file name                       *)
  66. (* AnOffset1    : offset of data to copy                 *)
  67. (* AFileName2   : destination file name                  *)
  68. (* AnOffset2    : destination address                    *)
  69. (* ALength      : length to copy (zero -> maximum)       *)
  70. (* AnOnProgress : progress callback event                *)
  71. (* ABufferSize  : buffer size to use                     *)
  72. (* ----------------------------------------------------- *)
  73. (* Copie un segment de fichier dans un fichier existant  *)
  74. (* AFileName1   : nom du fichier source                  *)
  75. (* AnOffset1    : adresse des données a copier           *)
  76. (* AFileName2   : nom du fichier de destination          *)
  77. (* AnOffset2    : adresse de destination                 *)
  78. (* ALength      : longueur à copier  (zéro -> maximum)   *)
  79. (* AnOnProgress : évènement de progression en retour     *)
  80. (* ABufferSize  : taille de buffer à utiliser            *)
  81. (*********************************************************)
  82.  
  83. procedure DTCopyFileSegment
  84.         (
  85.         const AFileName1        : string;
  86.         const AnOffset1         : Int64;
  87.         const AFileName2        : string;
  88.         const AnOffset2         : Int64;
  89.         const ALength           : Int64;
  90.         const AnOnProgress      : CSFSFileProgress = nil;
  91.         const ABufferSize       : Int64 = CSFSDefBufSize
  92.         );
  93.  
  94. (*********************************************************)
  95. (* DTCopyStreamSegToNewFile                              *)
  96. (* ----------------------------------------------------- *)
  97. (* Copy a segment of stream in a new file                *)
  98. (* AStream      : source stream                          *)
  99. (* AnOffset     : offset of data to copy                 *)
  100. (* ALength      : length to copy (zero -> maximum)       *)
  101. (* AFileName    : destination name of file to create     *)
  102. (* AnOnProgress : progress callback event                *)
  103. (* ABufferSize  : buffer size to use                     *)
  104. (* ----------------------------------------------------- *)
  105. (* Copie un segment de flux dans un nouveau fichier      *)
  106. (* AStream      : flux source                            *)
  107. (* AnOffset     : adresse des données à copier           *)
  108. (* ALength      : longueur à copier  (zéro -> maximum)   *)
  109. (* AFileName    : nom du fichier de destination à créer  *)
  110. (* AnOnProgress : évènement de progression en retour     *)
  111. (* ABufferSize  : taille de buffer à utiliser            *)
  112. (*********************************************************)
  113.  
  114. Procedure DTCopyStreamSegToNewFile
  115.         (
  116.         const AStream           : TStream;
  117.         const AnOffset          : Int64;
  118.         const ALength           : Int64;
  119.         const AFileName         : string;
  120.         const AnOnProgress      : CSFSFileProgress = nil;
  121.         const ABufferSize       : Int64 = CSFSDefBufSize
  122.         );
  123.  
  124. (*********************************************************)
  125. (* DTCopyFileSegToNewFile                                *)
  126. (* ----------------------------------------------------- *)
  127. (* Copy a segment of file in a new file                  *)
  128. (* AFileName1   : source file name                       *)
  129. (* AnOffset     : offset of data to copy                 *)
  130. (* ALength      : length to copy (zero -> maximum)       *)
  131. (* AFileName2   : destination name of file to create     *)
  132. (* AnOnProgress : progress callback event                *)
  133. (* ABufferSize  : buffer size to use                     *)
  134. (* ----------------------------------------------------- *)
  135. (* Copie un segment de fichier dans un nouveau fichier   *)
  136. (* AFileName1   : fichier source                         *)
  137. (* AnOffset     : adresse des données à copier           *)
  138. (* ALength      : longueur à copier  (zéro -> maximum)   *)
  139. (* AFileName2   : nom du fichier de destination à créer  *)
  140. (* AnOnProgress : évènement de progression en retour     *)
  141. (* ABufferSize  : taille de buffer à utiliser            *)
  142. (*********************************************************)
  143.  
  144. Procedure DTCopyFileSegToNewFile
  145.         (
  146.         const AFileName1        : string;
  147.         const AnOffset          : Int64;
  148.         const ALength           : Int64;
  149.         const AFileName2        : string;
  150.         const AnOnProgress      : CSFSFileProgress = nil;
  151.         const ABufferSize       : Int64 = CSFSDefBufSize
  152.         );
  153.  
  154.  
  155. (*********************************************************)
  156. (***)                                                 (***)
  157. (***)                 IMPLEMENTATION                  (***)
  158. (***)                                                 (***)
  159. (*********************************************************)
  160.  
  161. uses SysUtils;
  162.  
  163. {---------------------------------------------------------}
  164.  
  165. procedure DTCopyStreamSegment
  166.         (
  167.         const AStream1          : TStream;
  168.         const AnOffset1         : Int64;
  169.         const AStream2          : TStream;
  170.         const AnOffset2         : Int64;
  171.         const ALength           : Int64;
  172.         const AnOnProgress      : CSFSFileProgress = nil;
  173.         const ABufferSize       : Int64 = CSFSDefBufSize
  174.         );
  175. var TotalRemaining,BufferToConsider:Int64;
  176.     Offset1,Offset2,Length:Int64;
  177.     Buffer:PByte;
  178.  begin
  179.   if AnOffset1 < 0
  180.      then Offset1 := 0
  181.      else Offset1 := AnOffset1;
  182.   if AnOffset2 < 0
  183.      then Offset2 := 0
  184.      else Offset2 := AnOffset2;;
  185.   if ALength > 0
  186.      then Length := ALength
  187.      else Length := AStream1.Size-Offset1;
  188.   Buffer:=nil;
  189.   try
  190.    AStream1.Seek(Offset1,soFromBeginning);
  191.    AStream2.Seek(Offset2,soFromBeginning);
  192.    GetMem(Buffer,ABufferSize);
  193.    TotalRemaining:=Length;
  194.    repeat
  195.     if assigned(AnOnProgress)
  196.        then AnOnProgress(Length-TotalRemaining);
  197.      if TotalRemaining > ABufferSize
  198.         then BufferToConsider := ABufferSize
  199.         else BufferToConsider := TotalRemaining;
  200.      AStream1.ReadBuffer(Buffer^,BufferToConsider);
  201.      AStream2.WriteBuffer(Buffer^,BufferToConsider);
  202.      Dec(TotalRemaining,BufferToConsider);
  203.    until (TotalRemaining = 0)
  204.   finally
  205.    if assigned(Buffer) then FreeMem(Buffer);
  206.   end;
  207.   if assigned(AnOnProgress)
  208.      then AnOnProgress(Length-TotalRemaining);
  209.  end;
  210.  
  211. {---------------------------------------------------------}
  212.  
  213. procedure DTCopyFileSegment
  214.         (
  215.         const AFileName1        : string;
  216.         const AnOffset1         : Int64;
  217.         const AFileName2        : string;
  218.         const AnOffset2         : Int64;
  219.         const ALength           : Int64;
  220.         const AnOnProgress      : CSFSFileProgress = nil;
  221.         const ABufferSize       : Int64 = CSFSDefBufSize
  222.         );
  223. var Stream1,Stream2:TFileStream;
  224. begin
  225.   Stream1:=nil;
  226.   Stream2:=nil;
  227.   try
  228.    Stream1 := TFileStream.Create
  229.               (AFileName1,fmOpenRead or fmShareDenyWrite);
  230.    Stream2 := TFileStream.Create
  231.               (AFileName2,fmOpenReadWrite or fmShareExclusive);
  232.    DTCopyStreamSegment(Stream1,AnOffset1,Stream2,AnOffset2,
  233.                        ALength,AnOnProgress,ABufferSize);
  234.   finally
  235.    if assigned(Stream1) then Stream1.Free;
  236.    if assigned(Stream2) then Stream2.Free;
  237.   end;
  238.  end;
  239.  
  240. {---------------------------------------------------------}
  241.  
  242. Procedure DTCopyStreamSegToNewFile
  243.         (
  244.         const AStream           : TStream;
  245.         const AnOffset          : Int64;
  246.         const ALength           : Int64;
  247.         const AFileName         : string;
  248.         const AnOnProgress      : CSFSFileProgress = nil;
  249.         const ABufferSize       : Int64 = CSFSDefBufSize
  250.         );
  251. var StreamDest:TFileStream;
  252. begin
  253.   StreamDest:=nil;
  254.   try
  255.    StreamDest := TFileStream.Create
  256.                  (AFileName,fmCreate or fmShareExclusive);
  257.    DTCopyStreamSegment(AStream,AnOffset,StreamDest,0,
  258.                        ALength,AnOnProgress,ABufferSize);
  259.   finally
  260.    if assigned(StreamDest) then StreamDest.Free;
  261.   end;
  262.  end;
  263.  
  264. {---------------------------------------------------------}
  265.  
  266. Procedure DTCopyFileSegToNewFile
  267.         (
  268.         const AFileName1        : string;
  269.         const AnOffset          : Int64;
  270.         const ALength           : Int64;
  271.         const AFileName2        : string;
  272.         const AnOnProgress      : CSFSFileProgress = nil;
  273.         const ABufferSize       : Int64 = CSFSDefBufSize
  274.         );
  275. var Stream1,Stream2:TFileStream;
  276. begin
  277.   Stream1:=nil;
  278.   Stream2:=nil;
  279.   try
  280.    Stream1 := TFileStream.Create
  281.               (AFileName1,fmOpenRead or fmShareDenyWrite);
  282.    Stream2 := TFileStream.Create
  283.               (AFileName2,fmCreate or fmShareExclusive);
  284.    DTCopyStreamSegment(Stream1,AnOffset,Stream2,0,
  285.                        ALength,AnOnProgress,ABufferSize);
  286.   finally
  287.    if assigned(Stream1) then Stream1.Free;
  288.    if assigned(Stream2) then Stream2.Free;
  289.   end;
  290.  end;
  291.  
  292. {---------------------------------------------------------}
  293.  
  294. end.