[Lazarus] Can't copy TMemoryStream to TProcess.Input

Leonardo M. Ramé l.rame at griensu.com
Sat Apr 6 16:55:41 CEST 2013


On 2013-04-06 00:04:07 +0200, Mattias Gaertner wrote:
> On Fri, 5 Apr 2013 17:33:22 -0300
> Leonardo M. Ramé <l.rame at griensu.com> wrote:
> 
> > Hi, it must be that I've been working for more than 8 hrs but I can't find where the problem is...
> > 
> > I need to pass a file via stdIn to TProcess, then capture the StdOut. This
> > program should do what I expect, but, instead it hangs after writing aprox
> > 293000 bytes to Proc.Input stream.
> > 
> > Can you take a look at it?. 
> > 
> > program test;
> > 
> > {$mode objfpc}{$H+}
> > 
> > uses
> >   SysUtils, Classes, 
> >   process,
> >   math;
> > 
> > 
> > function CompressLZMA(AStream: TMemoryStream): TMemoryStream;
> > var
> >   Proc: TProcess;
> >   lBuffer: array [0..2048] of byte;
> >   ReadCount: integer;
> >   lPos: LongInt;
> > begin
> >   Result := TMemoryStream.Create;
> >   AStream.Position:= 0;
> >   writeln('-1-');
> >   Proc := TProcess.Create(nil); //Create a new process
> >   try
> >     Proc.Executable := '/usr/bin/lzma'; //Run lzma
> >     Proc.Parameters.Add('--compress');
> >     Proc.Options := [poUsePipes, poStderrToOutPut];
> >     Proc.Execute; 
> > 
> >     writeln(format('Writing %d bytes...', [AStream.Size]));
> > 
> >     lPos := 0;
> >     while(lPos < AStream.Size) do
> >     begin
> >       writeln(format('Pos: %d - Size: %d', [lPos, AStream.Size]));
> >       ReadCount := AStream.Read(lBuffer, SizeOf(lBuffer));
> >       Proc.Input.Write(lBuffer, ReadCount);
> >       lPos := lPos + ReadCount;
> 
> After every write to Input, read all available from Output and StdErr.
> 
> Mattias
> 

Thanks Mattias, I went a step further.

Sadly now I'm getting an "unexpected end of input" error when I try to
decompress the generated file using "lzma -d -c output.lzma >
output.dcm".

Attached is the modified program.

Regards,
-- 
Leonardo M. Ramé
http://leonardorame.blogspot.com
-------------- next part --------------
program test;

{$mode objfpc}{$H+}

uses
  SysUtils, Classes, 
  process,
  math;

function CompressLZMA(AStream: TMemoryStream): TMemoryStream;
var
  Proc: TProcess;
  lBuffer: array [0..2047] of byte;
  ReadCount: longint;
  WriteCount: longint;
begin
  Result := TMemoryStream.Create;
  AStream.Position:= 0;
  Proc := TProcess.Create(nil); 
  try
    Proc.Executable := '/usr/bin/lzma';
    Proc.Parameters.Add('-z');
    Proc.Parameters.Add('-c');
    Proc.Options := [poUsePipes, poStderrToOutPut];
    Proc.Execute; 

    while(AStream.Position < AStream.Size) do
    begin
      ReadCount := AStream.Read(lBuffer, SizeOf(lBuffer));
      Proc.Input.Write(lBuffer, ReadCount);
      while (Proc.Output.NumBytesAvailable > 0) do
      begin
        WriteCount := Min(SizeOf(lBuffer), Proc.Output.NumBytesAvailable); 
        Proc.Output.Read(lBuffer, WriteCount);
        Result.Write(lBuffer, WriteCount);
      end;
    end;
    Result.Position:= 0;
  finally
    Proc.Free;
  end;
end; 

var
  lStr: TMemoryStream;
begin
  lStr := TMemoryStream.Create;
  try
    lStr.LoadFromFile('mg.dcm');
    CompressLZMA(lStr).SaveToFile('output.lzma');    
  finally
    lStr.Free;
  end;
end.


More information about the Lazarus mailing list