15 мая 2023 года "Исходники.РУ" отмечают своё 23-летие!
Поздравляем всех причастных и неравнодушных с этим событием!
И огромное спасибо всем, кто был и остаётся с нами все эти годы!

Главная Форум Журнал Wiki DRKB Discuz!ML Помощь проекту




Как склеить несколько файлов в один и наоборот (работа с TStream)

Как-то раз понадобилось запихнуть много файлов в один поток(stream), так как необходимо было отправить их как один файл. Вот, что для этого было сделано:

Procedure TForm1.ThisISHowIPutFilesIn ;
var
  ABigFileStream, SomeSmallFiles : TMemoryStream ;

begin
  ABigFileStream := TMemoryStream.Create ;
  try
    SomeSmallFiles := TMemoryStream.Create ;
     try
      SomeSmallFiles.LoadFromFile('C:\SomeSmalFile1.txt');
      AddToStream(SomeSmallFiles,ABigFileStream);
      SomeSmallFiles.LoadFromFile('C:\SomeSmalFile2.txt');
      AddToStream(SomeSmallFiles,ABigFileStream);
      // enz
     finally
      SomeSmallFiles.Free ;
     end;
  ABigFileStream.SaveToFile('C:\MrBig.DDD')
  finally
  ABigFileStream.free ;
  end;
end;

Procedure TForm1.ThisISHowIGetStufOut ;
var
  ABigFileStream, SomeSmallFiles : TMemoryStream ;

begin
  ABigFileStream := TMemoryStream.Create ;
  try
    ABigFileStream.LoadFromFile('C:\MrBig.DDD');
    SomeSmallFiles := TMemoryStream.Create ;
     try
      GetFromStream(ABigFileStream,SomeSmallFiles,0);
      SomeSmallFiles.SaveToFile('C:\SomeSmalFile1.txt');
      GetFromStream(ABigFileStream,SomeSmallFiles,1);
      SomeSmallFiles.SaveToFile('C:\SomeSmalFile2.txt');
      // и т.д.
     finally
      SomeSmallFiles.Free ;
     end;
  finally
  ABigFileStream.free ;
  end;
end;

Procedure TForm1.AddToStream ( Source , Dest : TStream );
var
Size : Integer ;
begin
Source.position := 0 ;
// Сохраняем размер, помещая его в первый байт
Size := Source.Size ;
Dest.Write(Size,SizeOf(Integer));
Dest.CopyFrom(Source,Source.size);
end;

Procedure TForm1.GetFromStream ( Source , Dest : TStream ; Index : Integer  );
Var
  Size , I : Integer ;

begin
Source.Position := 0 ;
For i := 0 to index-1 do
   begin
     Source.Read(Size,SizeOf(Integer));
     Source.Position := Source.Position + Size ;
   end;
// Если маркёр в файле равен размеру, то что-то пошло не так :(
if Source.position = Source.Size then Raise EAccessViolation.Create('Index Out Of Bounds') ;
// Получаем желаемый размер файла
Source.Read(Size,SizeOf(Integer));
// Очищаем буфер у Dest
Dest.Position := 0 ;
Dest.Size := 0 ;
Dest.CopyFrom(Source,Size);
end;