【问题标题】:C# Console receive input with pipeC# 控制台使用管道接收输入
【发布时间】:2010-09-17 00:06:41
【问题描述】:

我知道如何使用参数对控制台应用程序进行编程,例如:myProgram.exe param1 param2。

我的问题是,如何使我的程序与 | 一起工作,例如:echo "word" |我的程序.exe?

【问题讨论】:

    标签: c# pipe


    【解决方案1】:

    您需要像阅读用户输入一样使用Console.Read()Console.ReadLine()。管道透明地替换用户输入。你不能轻易地使用两者(尽管我确信这很有可能......)。

    编辑:

    一个简单的cat风格的程序:

    class Program
    {
        static void Main(string[] args)
        {
            string s;
            while ((s = Console.ReadLine()) != null)
            {
                Console.WriteLine(s);
            }
    
        }
    }
    

    当运行时,正如预期的那样,输出:

    C:\...\ConsoleApplication1\bin\Debug>echo "Foo bar baz" | ConsoleApplication1.exe “Foo bar baz” C:\...\ConsoleApplication1\bin\Debug>

    【讨论】:

    • 您的示例是否适用于:echo "Foo bar baz" | ConsoleApplication1.exe | ConsoleApplication1.exe ?
    • 是的。使用较低级别的类比,管道真正发生的事情是第一个应用程序的 Stdout 流被插入管道中下一个应用程序的 Stdin 流。控制台的标准输入通过第一个应用程序,并显示最后一个应用程序的标准输出。
    • 如果您使用的是二进制数据:stackoverflow.com/questions/1562417/…
    • 为什么要检查 ReadLine == null,它是否返回 null? (如果没有输入,它不会返回空字符串)。 stackoverflow.com/questions/26338571/…
    • @barlop 不,它不会返回空字符串。那么你将如何检索空行呢? Console.ReadLine 的文档指出,如果没有更多要读取的行,它将返回 null:msdn.microsoft.com/de-de/library/…
    【解决方案2】:

    Console.In 是对环绕标准输入流的 TextReader 的引用。当向您的程序输送大量数据时,使用这种方式可能会更容易。

    【讨论】:

      【解决方案3】:

      提供的示例有问题。

        while ((s = Console.ReadLine()) != null)
      

      如果程序在没有管道数据的情况下启动,将等待输入。所以用户必须手动按任意键退出程序。

      【讨论】:

      • 这更值得作为评论,其他人已经解决了这个问题并提供了解决方案
      【解决方案4】:

      当数据未通过管道传输时,以下内容不会暂停应用程序的输入和工作。有点小技巧;并且由于错误捕获,当进行大量管道调用时性能可能会有所下降,但是......很容易。

      public static void Main(String[] args)
      {
      
          String pipedText = "";
          bool isKeyAvailable;
      
          try
          {
              isKeyAvailable = System.Console.KeyAvailable;
          }
          catch (InvalidOperationException expected)
          {
              pipedText = System.Console.In.ReadToEnd();
          }
      
          //do something with pipedText or the args
      }
      

      【讨论】:

      【解决方案5】:

      这是从其他解决方案加上 peek() 组合而成的另一个替代解决方案。

      如果没有 Peek(),我在执行 "type t.txt | prog.exe" 时,如果 t.txt 是一个多行文件,我会遇到应用程序不会在最后没有 ctrl-c 的情况下返回。但只是“prog.exe”或“echo hi | prog.exe”工作正常。

      此代码仅用于处理管道输入。

      static int Main(string[] args)
      {
          // if nothing is being piped in, then exit
          if (!IsPipedInput())
              return 0;
      
          while (Console.In.Peek() != -1)
          {
              string input = Console.In.ReadLine();
              Console.WriteLine(input);
          }
      
          return 0;
      }
      
      private static bool IsPipedInput()
      {
          try
          {
              bool isKey = Console.KeyAvailable;
              return false;
          }
          catch
          {
              return true;
          }
      }
      

      【讨论】:

      【解决方案6】:

      这是这样做的方法:

      static void Main(string[] args)
      {
          Console.SetIn(new StreamReader(Console.OpenStandardInput(8192))); // This will allow input >256 chars
          while (Console.In.Peek() != -1)
          {
              string input = Console.In.ReadLine();
              Console.WriteLine("Data read was " + input);
          }
      }
      

      这允许两种使用方法。从标准输入读取:

      C:\test>myProgram.exe
      hello
      Data read was hello
      

      或从管道输入读取:

      C:\test>echo hello | myProgram.exe
      Data read was hello
      

      【讨论】:

        【解决方案7】:

        在 .NET 4.5 中是

        if (Console.IsInputRedirected)
        {
            using(stream s = Console.OpenStandardInput())
            {
                ...
        

        【讨论】:

        • 嗨,我似乎无法使用这段代码,有什么想法吗?
        【解决方案8】:

        这也适用于

        c:\MyApp.exe

        我必须使用 StringBuilder 来操作从 Stdin 捕获的输入:

        public static void Main()
        {
            List<string> salesLines = new List<string>();
            Console.InputEncoding = Encoding.UTF8;
            using (StreamReader reader = new StreamReader(Console.OpenStandardInput(), Console.InputEncoding))
            {
                string stdin;
                do
                {
                    StringBuilder stdinBuilder = new StringBuilder();
                    stdin = reader.ReadLine();
                    stdinBuilder.Append(stdin);
                    var lineIn = stdin;
                    if (stdinBuilder.ToString().Trim() != "")
                    {
                        salesLines.Add(stdinBuilder.ToString().Trim());
                    }
        
                } while (stdin != null);
        
            }
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2019-04-11
          • 1970-01-01
          • 1970-01-01
          • 2014-03-13
          • 2018-03-17
          • 1970-01-01
          相关资源
          最近更新 更多