2013-03-21 60 views
6

如何從Delphi控制檯應用程序寫入stdout?如何在Delphi中將二進制數據寫入stdout?

這是我的嘗試。我已經根據相關信息,我能找到操縱這個簡單的測試應用程序,讀取文件從磁盤,並將其輸出到控制檯標準輸出:

program ConsoleOut; 
{$APPTYPE CONSOLE} 
uses 
    Classes, Windows, SysUtils; 

var 
    S: TMemoryStream; 
    OutputStream: THandleStream; 
    ss: string; 
    Buffer: PByte; 
    i: Integer; 
begin 
    S := TMemoryStream.Create; 
    S.LoadFromFile('1.jpg'); 
    S.Seek(0, soFromBeginning); 

    //Am I right that from now on writing to OutputStream will write to stdout? 
    OutputStream := THandleStream.Create(GetStdHandle(STD_OUTPUT_HANDLE)); 

    GetMem(Buffer, S.Size); 
    S.ReadBuffer(Buffer^, S.Size); 
    i := OutputStream.Write(Buffer^, S.Size); //i = 0 here for some reason 
    FreeMem(Buffer, S.Size); 

    Writeln(i, ' byte written to output'); 
    Readln(ss); //Don't exit app to read previous line 
    S.Free; 
end. 

但由於某種原因失敗。你能否引導我以正確的方式寫入標準輸出?

+0

好奇爲什麼你想把二進制噪聲寫入控制檯?你提到了文本到語音的一些內容。爲什麼不命名管道? – 2013-03-22 01:14:48

+1

命名管道對標準輸出有什麼優勢? – Kromster 2013-03-22 05:17:05

+0

專爲Windows上的嚴重數據傳輸而非用戶界面而設計。 Unix標準輸出通常用作匿名數據管道。 DOS和Windows不經常使用這個。如你所知。 – 2013-03-22 11:35:23

回答

7

你的做法是合理的。但是,如果stdout連接到控制檯,則代碼將失敗。在流寫入後致電GetLastError顯示錯誤代碼ERROR_NOT_ENOUGH_MEMORY

沒有足夠的存儲空間可用於處理此命令。

如果您將stdout重定向到一個文件,那麼您的代碼將正常工作。當然你並不是真的想把二進制數據傳給控制檯。這隻會在控制檯上放入不可讀的內容,並使計算機發出嘟嘟聲!

如果必須輸出到控制檯,那麼你就需要找出控制檯設備緩衝區有多大,並寫信給它適當大小的塊。我必須承認,我不確定你如何去做。你可以使用試驗和錯誤,但這並不吸引我。推測有一種方法可以查詢控制檯以找出信息。

望着用於WriteConsole的文檔,似乎64K爲上限。事實上,如果我爲你的句柄流寫空格,那麼我一次就可以寫入近64K。但是,如果我編寫原始JPEG二進制數據,則會提前發佈。所以我認爲這也是問題的一部分 - 不要將JPEG轉儲到控制檯上。其他

一個評論。由於您將文件的內容讀入內存流,因此不需要分配中間緩衝區。你可以直接寫S.Memory^

+1

感謝您的提示,我認爲如果控制檯是空的,它不起作用,但將stdout重定向到一個文件(「appname.exe> out.jpg」)工作得很好。 – Kromster 2013-03-21 08:56:40

+1

在旁註:我正在開發一個應用程序,需要生成和輸出文本到語音轉換爲標準輸出,所以是的,這是二進制數據和很多它(很少Mb)。但是你的回答涵蓋了很多方面,所以請不要削減它,這對其他人有用) – Kromster 2013-03-21 09:08:03

+0

@KromStern:你最後的評論沒有意義。如果你正在做'文本到語音到標準輸出',然後把'標準輸出'重定向到一個文件,你可以簡單地用'文本到語音文件'來剪切'標準輸出'中間人。寫入控制檯立即將該輸出重定向到文件沒有意義。 – 2013-03-22 01:44:29

相關問題