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

Leonardo M. Ramé l.rame at griensu.com
Sat Apr 6 19:48:18 CEST 2013


On 2013-04-06 13:22:39 -0300, Leonardo M. Ramé wrote:
> On 2013-04-06 17:46:06 +0200, Mattias Gaertner wrote:
> > On Sat, 6 Apr 2013 12:37:06 -0300
> > Leonardo M. Ramé <l.rame at griensu.com> wrote:
> > 
> > >[...]
> > > > Check return value of Proc.Input.Write.
> > > > And call Proc.CloseInput when your input was written completely.
> > > > 
> > > > 
> > > 
> > > Mmm, I'm getting the same result. 
> > > 
> > > I attached the new code.
> > 
> > When you give Proc.Input.Write 200 bytes and it returns that the other
> > process could only process 100 of them. What bytes do you have to write
> > next?
> > 
> 
> Sorry, I'm not getting it. Which other process?, apart from that,
> Proc.Input.Write is always returning the sizeof(buffer) except when it
> reaches the end, where it can be less than it.
> 
> It seems that the Proc.Input part is ok, aparently the Proc.Output is
> wrong :(
> 
> I attached a slightly modified code.
> 

Finally got it working, I was forgetting to read the last part of the
Output stream. ...I still don't know why this last chunk of bytes
doesn't show up in NumBytesAvailable.

I attached the code.

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

{$mode objfpc}{$H+}

uses
  SysUtils, Classes, 
  process,
  math;

const
  READ_BYTES = 2048;

procedure CompressLZMA(InStream, OutStream: TMemoryStream);
var
  Proc: TProcess;
  lInBuffer: array [0..2047] of byte;
  BytesRead: longint;
  NumBytes: longint;
begin
  InStream.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; 
  
    BytesRead := 0;
    repeat
      NumBytes := InStream.Read(lInBuffer, SizeOf(lInBuffer));
      Proc.Input.Write(lInBuffer, NumBytes);
      if InStream.Position >= InStream.Size then
        Proc.CloseInput; 
      while Proc.Output.NumBytesAvailable > 0 do
      begin          
        OutStream.SetSize(BytesRead + READ_BYTES);
        NumBytes := Proc.Output.Read((OutStream.Memory + BytesRead)^, READ_BYTES);
        if NumBytes > 0
        then begin
          Inc(BytesRead, NumBytes);
        end;
      end;
    until Proc.Input = nil;
    // read the last part
    repeat
      OutStream.SetSize(BytesRead + READ_BYTES);
      NumBytes := Proc.Output.Read((OutStream.Memory + BytesRead)^, READ_BYTES);
      if NumBytes > 0 then 
        Inc(BytesRead, NumBytes);
    until NumBytes <= 0;  
    OutStream.SetSize(BytesRead);
    OutStream.Position:= 0;
  finally
    Proc.Free;
  end;
end; 

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


More information about the Lazarus mailing list