2014-01-07 74 views
0

我正在使用TProcess和this freepascal wiki頁面的建議讀取Lazarus中的大流程輸出數據。Lazarus(freepascal)讀取TProcess的大輸出

維基頁面提示創建一個循環讀取過程輸出數據是這樣的:

// ... If you want to read output from an external process, this is the code you should adapt for production use. 

while True do 
    begin   
    MemStream.SetSize(BytesRead + 2024); // make sure we have room 
    NumBytes := OurProcess.Output.Read((MemStream.Memory + BytesRead)^, READ_BYTES); 
    if NumBytes > 0 
    then begin 
     Inc(BytesRead, NumBytes); 
     Write('.') //Output progress to screen. 
    end else 
     BREAK // Program has finished execution. 
    end; 

// "Then read the MemStream to do your job" 

維基頁面還提到,調用程序應該從輸出管道讀取,以防止其變滿。

那麼,多少數據使輸出管道滿了?

爲什麼我們應該在上面的循環中使用MemStream(TMemoryStream)而不是直接從OurProcess.Output流中讀取(使用bytesAvailable等)?

我正在閱讀80MB的流程中的wav數據,我注意到MemStreamOurProcess.Output流具有相同的數據量!內存使用量增加了一倍。因此,來自wiki的建議方法不能被認爲是有效的或優化的。或者有什麼我失蹤?

回答

0

Afaik輸出/輸入流是管道的流形式,而不是內存流。您看到的值是從OS句柄中檢索的,而不是從分配給FPC應用程序本身的內存中檢索的。

這就像你可以要求磁盤上的文件的大小而不讀取整個文件一樣。

+0

因此'.output'流在'.execute'完成時不會包含整個數據嗎?多少數據'.output'可以保證? – Vassilis

0
procedure RunExternalAppInMemo(DosApp:String;AMemo:TMemo); 

    const READ_BYTES = 2048; 
    var 
    aProcess: TProcess; //TProcess is crossplatform is best way 
    MemStream: TMemoryStream; 
    NumBytes: LongInt; 
    BytesRead: LongInt; 
    Lines: TStringList; 
    begin 
    // A temp Memorystream is used to buffer the output 
    MemStream := TMemoryStream.Create; 
    Lines :=TStringList.Create; 
    BytesRead := 0; 

    aProcess := TProcess.Create(nil); 
    aProcess.CommandLine := DosApp; 
    aprocess.ShowWindow := swoHIDE; 
    AProcess.Options := AProcess.Options + [poUsePipes]; 

    aProcess.Execute; 
    while aProcess.Running do 
    begin 
     // make sure we have room 
     MemStream.SetSize(BytesRead + READ_BYTES); 

     // try reading it 
     NumBytes := aProcess.Output.Read((MemStream.Memory + BytesRead)^, READ_BYTES); 
     if NumBytes > 0 // All read() calls will block, except the final one. 
      then Inc(BytesRead, NumBytes) 
     else 
      BREAK // Program has finished execution. 
    end; 
    MemStream.SetSize(BytesRead); 
    Lines.LoadFromStream(MemStream); 
    AMemo.lines.AddStrings(Lines); 
    aProcess.Free; 
    Lines.Free; 
    MemStream.Free; 
    end;