从 Ada 中的管道读取输入

Read input from a pipe in Ada

我有一段代码(见下文)从作为命令行参数给出的文件中读取数据。我想添加对能够从管道读取输入的支持。例如,当前版本读取数据为 main <file_name>,而行 cmd1 | main 也应该可以做一些事情。这是从文件中读取数据的来源:

procedure main is

    File : Ada.Text_IO.File_Type;

begin

   if Ada.Command_Line.Argument_Count /= 1 then

      return;

   else

      Ada.Text_IO.Open (
         File => File,
         Mode => In_File,
         Name => Ada.Command_Line.Argument (1));

      while (not Ada.Text_IO.End_Of_File (File)) loop
         -- Read line using Ada.Text_IO.Get_Line
         -- Process the line
      end loop;

      Ada.Text_IO.Close (File);

end main;

如果我没理解错的话,管道只是 Ada 中的一种非常规文件类型。但是我该如何处理呢?

您甚至不需要创建文件就可以从管道读取数据。

with Ada.Text_IO;
procedure main is

    begin

      loop
        exit when Ada.Text_IO.End_Of_File;
        Ada.Text_IO.Put_Line("Echo" &Ada.Text_IO.Get_Line);
      end loop;
end main;

然后 type ..\src\main.adb | main.exe 有效。

引用自the ARM...

The library package Text_IO has the following declaration:

...
package Ada.Text_IO is
...
   -- Control of default input and output files

   procedure Set_Input (File : in File_Type);
   procedure Set_Output(File : in File_Type);
   procedure Set_Error (File : in File_Type);

   function Standard_Input  return File_Type;
   function Standard_Output return File_Type;
   function Standard_Error  return File_Type;

   function Current_Input   return File_Type;
   function Current_Output  return File_Type;
   function Current_Error   return File_Type;

允许您将默认管道 stdin, stdout, stderr 作为文件进行操作;作为预先打开的文件(输入和输出管道)或允许您将标准输出重定向到您自己的文件等。

This example 显示将标准管道之一重定向到文件并将其恢复到系统提供的文件。或者,可以调用 File I/O 子程序,并将 File 参数设置为例如Ada.Text_IO.Standard_Output 并且应该按预期工作 - 输出到终端或任何您在命令行上通过管道传输 stdout 的内容。

如果您正在读取和写入的数据不是文本,Direct_IO, Sequential_IO, Stream_IO 等应该提供类似的工具。

Timur 的回答表明你可以直接读写这些管道;这个答案的方法允许您将标准管道与其他文件统一处理,这样您就可以 I/O 通过文件或管道使用相同的代码。例如,如果提供了命令行文件名,则使用该文件,否则将您的文件指向 Standard_Output.

如果您询问命令行 cmd1|main|grep "hello" 中发生了什么,是的,cmd1 的输出位于名为 stdout(在 C 中)或 Standard_Output( Ada) 通过(Unix 特定的管道命令)连接 |到用 Ada 编写的 main 程序的 Standard_Input。反过来,它的 Standard_Output 被输送到它搜索 "hello".

的 grep 的 stdin

如果您问的是如何打开和访问命名管道,我怀疑这是 OS 特定的,并且可能是一个更难的问题。

(在这种情况下,this Stack Exchange Q&A 可能会有所帮助)。

None 这些似乎真正回答了您的问题。管道只是将另一个程序的标准输出作为您程序的标准输入,因此您可以通过读取 Standard_Input.

来读取管道。

函数 Current_Input return 是 File_Type。它最初是 returns Standard_Input,但是调用 Set_Input 将它更改为 return 无论您传递给 Set_Input。因此,如果没有给出文件,如何从 Standard_Input 读取,如果有,如何从给定文件读取,如下所示:

File : File_Type;

if Argument_Count > 0 then
   Open (File => File, Name => Argument (1), Mode => In_File);
   Set_Input (File => File);
end if;

All_Lines : loop
   exit All_Lines when End_Of_File (Current_Input);

   Process (Line => Get_Line (Current_Input) );
end loop All_Lines;