如何在Delphi中将二进制数据写入stdout?

时间:2013-03-21 07:29:39

标签: delphi console 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.

但由于某种原因,它失败了。你能指导我正确地写一下stdout吗?

1 个答案:

答案 0 :(得分:7)

你的方法很健全。但是,如果将stdout附加到控制台,则代码将失败。在流写入后调用GetLastError会显示错误代码ERROR_NOT_ENOUGH_MEMORY

  

没有足够的存储空间可用于处理此命令。

如果将stdout重定向到文件,那么您的代码将正常工作。当然,你真的不想将二进制数据喷射到控制台。这只会在控制台上放置不可读的内容,让计算机发出嘟嘟声!

如果必须输出到控制台,那么您需要找出控制台设备缓冲区的大小,并以适当大小的块写入它。我必须承认,我不确定你是怎么做的。您可以使用反复试验,但这对我没有吸引力。据推测,有一种方法可以查询控制台以找出信息。

查看WriteConsole的文档,似乎64K是上限。事实上,如果我在句柄流中写入空格,那么我可以一次写入近64K。但是,如果我写原始的JPEG二进制数据,那么它会更早地发出。所以我认为这也是问题的一部分 - 不要将JPEG转储到控制台上。

另一条评论。由于您将文件的内容读入内存流,因此无需分配中间缓冲区。您可以直接撰写S.Memory^