Delphi Tokyo for Linux:将文件内容流式传输到标准输出(控制台输出)

Delphi Tokyo for Linux:将文件内容流式传输到标准输出(控制台输出),linux,delphi,debian,delphi-10.2-tokyo,Linux,Delphi,Debian,Delphi 10.2 Tokyo,关于如何将文件内容(在本例中为excel文件)流式传输到控制台输出,我已经研究了很长时间了。为Windows编译时,使用THandleStream和STDOUT(控制台输出)的句柄,就像在公园里散步一样。它使用Win32 API,因此在为Linux(顺便说一句,Debian)编译时显然无法工作 我正在寻找一个与此等效的: ... aFileStream := TFileStream.Create(FullFileName,fmOpenRead); // This creates the inpu

关于如何将文件内容(在本例中为excel文件)流式传输到控制台输出,我已经研究了很长时间了。为Windows编译时,使用
THandleStream
和STDOUT(控制台输出)的句柄,就像在公园里散步一样。它使用Win32 API,因此在为Linux(顺便说一句,Debian)编译时显然无法工作

我正在寻找一个与此等效的:

...
aFileStream := TFileStream.Create(FullFileName,fmOpenRead); // This creates the input stream
aOutputStream := THandleStream.Create(GetStdHandle(STD_OUTPUT_HANDLE)); // Here goes the output stream
aOutputStream.CopyFrom(aFileStream, aFileStream.Size); // And the copy operation
...

更新:以下内容似乎在Windows上起作用,但只要我切换到Linux,它就不会编译,因为
PAnsiChar
是未知的

...
f : File;
Buff : PAnsiChar;
BytesRead : integer;
ByteSize : integer;
iBuffRunner : integer;
...
AssignFile(F, 'details.xlsx');
Reset(F,1);
ByteSize := (fileSize(F));
GetMem(Buff,ByteSize);
BlockRead(F,Buff[0],ByteSize,BytesRead);
CloseFile(F);
for iBuffRunner := 0 to (Bytesize-1) do
  System.Write(Buff[iBuffRunner]);
FreeMem(Buff);
你能想出一些可能有用的办法吗

更新

const
    MaxBufSize = 4096;
var
    f             : File of Byte;
    tf            : File of Byte;
    Buff          : array of Byte;
    BytesRead     : integer;
    ByteSize      : integer;
    WillRead      : integer;
    iBufRunner    : integer;
begin
  AssignFile(F, 'details.xlsx');
  Reset(F);
  ByteSize := (fileSize(F));

  if ByteSize > MaxBufSize then
    BytesRead := MaxBufSize
  else
    BytesRead := ByteSize;
  SetLength(Buff, BytesRead);

  AssignFile(tf, 'test.xlsx');
  Rewrite(tf);

  try
    while ByteSize <> 0 do
    begin
      if ByteSize > BytesRead then
        WillRead := BytesRead
      else
        WillRead := ByteSize;
      BlockRead(F,Buff[0], WillRead);
      BlockWrite(tf,Buff[0], WillRead);
      for iBufRunner := 0 to (WillRead - 1) do
        System.Write(System.Output, UTF8Char(Buff[iBufRunner]));
      Dec(ByteSize, WillRead);
    end;
  finally
    SetLength(Buff,0);
    CloseFile(f);
    CloseFile(tf);
  end;
  System.Readln;
end;
嗨,雷米

再次感谢你的帮助!我就快到了,还在苦苦挣扎。您提到我应该能够对system.output执行块写入。但是,BlockWrite希望var F:File作为第一个参数,而System.Output的类型为TEXT

此外,对于我正在读取的文件,我使用的是“字节文件”而不是“文件”,我不确定如何适当地转换输出到控制台

这是此linux POC的当前状态:

这部分很好:阅读details.xlsx并将内容写入test.xlsx(基本上是副本)。目标文件与源文件相同

这一部分还不起作用,但最终我需要的是:将details.xlsx的内容写入stdout:

const
    MaxBufSize = 4096;
var
    f             : File of Byte;
    tf            : File of Byte;
    Buff          : array of Byte;
    BytesRead     : integer;
    ByteSize      : integer;
    WillRead      : integer;
begin
  AssignFile(F, 'details.xlsx');
  Reset(F);
  ByteSize := (fileSize(F));

  if ByteSize > MaxBufSize then
    BytesRead := MaxBufSize
  else
    BytesRead := ByteSize;
  SetLength(Buff, BytesRead);

  AssignFile(tf, 'test.xlsx');
  Rewrite(tf);

  try
    while ByteSize <> 0 do
    begin
      if ByteSize > BytesRead then
        WillRead := BytesRead
      else
        WillRead := ByteSize;
      BlockRead(F,Buff[0], WillRead);
      BlockWrite(tf,Buff[0], WillRead);
      //BlockWrite(System.Output, buff[0], WillRead);
      Dec(ByteSize, WillRead);
    end;
  finally
    SetLength(Buff,0);
    CloseFile(f);
    CloseFile(tf);
  end;
  System.Readln;
end;
const
MaxBufSize=4096;
变量
f:字节文件;
tf:字节文件;
Buff:字节数组;
字节读取:整数;
字节大小:整数;
WillRead:整数;
开始
赋值文件(F,'details.xlsx');
重置(F);
字节大小:=(文件大小(F));
如果ByteSize>MaxBufSize,则
字节读取:=MaxBufSize
其他的
字节读取:=字节大小;
设置长度(Buff,字节读取);
赋值文件(tf,'test.xlsx');
重写(tf);
尝试
而ByteSize 0可以
开始
如果字节大小>字节读取,则
WillRead:=字节读取
其他的
WillRead:=字节大小;
块读(F,Buff[0],WillRead);
块写入(tf,Buff[0],WillRead);
//块写入(System.Output,buff[0],WillRead);
Dec(ByteSize,WillRead);
结束;
最后
设置长度(Buff,0);
关闭文件(f);
关闭文件(tf);
结束;
系统Readln;
结束;
最终更新

const
    MaxBufSize = 4096;
var
    f             : File of Byte;
    tf            : File of Byte;
    Buff          : array of Byte;
    BytesRead     : integer;
    ByteSize      : integer;
    WillRead      : integer;
    iBufRunner    : integer;
begin
  AssignFile(F, 'details.xlsx');
  Reset(F);
  ByteSize := (fileSize(F));

  if ByteSize > MaxBufSize then
    BytesRead := MaxBufSize
  else
    BytesRead := ByteSize;
  SetLength(Buff, BytesRead);

  AssignFile(tf, 'test.xlsx');
  Rewrite(tf);

  try
    while ByteSize <> 0 do
    begin
      if ByteSize > BytesRead then
        WillRead := BytesRead
      else
        WillRead := ByteSize;
      BlockRead(F,Buff[0], WillRead);
      BlockWrite(tf,Buff[0], WillRead);
      for iBufRunner := 0 to (WillRead - 1) do
        System.Write(System.Output, UTF8Char(Buff[iBufRunner]));
      Dec(ByteSize, WillRead);
    end;
  finally
    SetLength(Buff,0);
    CloseFile(f);
    CloseFile(tf);
  end;
  System.Readln;
end;
const
MaxBufSize=4096;
变量
f:字节文件;
tf:字节文件;
Buff:字节数组;
字节读取:整数;
字节大小:整数;
WillRead:整数;
iBufRunner:整数;
开始
赋值文件(F,'details.xlsx');
重置(F);
字节大小:=(文件大小(F));
如果ByteSize>MaxBufSize,则
字节读取:=MaxBufSize
其他的
字节读取:=字节大小;
设置长度(Buff,字节读取);
赋值文件(tf,'test.xlsx');
重写(tf);
尝试
而ByteSize 0可以
开始
如果字节大小>字节读取,则
WillRead:=字节读取
其他的
WillRead:=字节大小;
块读(F,Buff[0],WillRead);
块写入(tf,Buff[0],WillRead);
对于iBufRunner:=0到(将读取-1)do
System.Write(System.Output,UTF8Char(Buff[iBufRunner]);
Dec(ByteSize,WillRead);
结束;
最后
设置长度(Buff,0);
关闭文件(f);
关闭文件(tf);
结束;
系统Readln;
结束;

我们找到了解决方案:使用UTF8Char而不是AnsiChar就成功了。(见最终更新)

您尝试过旧款了吗
AssignFile()
Write/Ln()
BlockWrite()
,等等……嗨,雷米,谢谢你的提示,我会给它一个机会,然后让你知道。嗨,雷米,这似乎对Win有效,但是,只要我切换到Linux,它就不会编译,因为PAnsiChar是未知的。你能想出一些可能有用的办法吗。。。f:文件;浅黄色:潘斯卡尔;字节读取:整数;字节大小:整数;iBuffRunner:integer。。。赋值文件(F,'details.xlsx');复位(F,1);字节大小:=(文件大小(F));GetMem(Buff,ByteSize);块读取(F,Buff[0],字节大小,字节读取);关闭文件(F);对于iBuffRunner:=0 to(Bytesize-1)do System.Write(Buff[iBuffRunner]);弗里曼(Buff);您应该编辑您的问题以显示代码,而不是将其发布在评论中。我为你更新了你的问题。在任何情况下,为了回答您的下一个问题,
(P)AnsiChar
在nextgen编译器中被禁用(这在Linux中非常愚蠢,因为它偏爱UTF-8处理),因此您可以使用
(P)Byte
。不过,我不建议在将整个文件写入STDOUT之前将其读入内存。分配一个固定的内存块,比如说1-4K大小的内存块,并在循环时以块的形式读取文件。这就是您的
THandleStream.CopyFrom()
解决方案在内部所做的。您不需要
Write()
输出单个字节,您可以与file变量一起使用。