Консоль C # получает ввод с конвейера - PullRequest
36 голосов
/ 14 октября 2008

Я знаю, как программировать консольное приложение с параметрами, например: myProgram.exe param1 param2.

Мой вопрос: как я могу заставить мою программу работать с |, например: echo "word" | myprogram.exe

Ответы [ 8 ]

43 голосов
/ 14 октября 2008

Вам нужно использовать Console.Read() и Console.ReadLine(), как если бы вы читали пользовательский ввод. Трубы прозрачно заменяют пользовательский ввод. Вы не можете использовать оба легко (хотя я уверен, что это вполне возможно ...).

Edit:

Простая программа в стиле 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>
15 голосов
/ 02 ноября 2010

Следующее не приостанавливает приложение для ввода и работает, когда данные или не переданы по трубопроводу. Немного взломать; и из-за перехвата ошибок производительность может уменьшаться при выполнении многочисленных вызовов по трубопроводу, но ... легко.

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
}
11 голосов
/ 14 марта 2015

в .NET 4.5 это

if (Console.IsInputRedirected)
{
    using(stream s = Console.OpenStandardInput())
    {
        ...
8 голосов
/ 20 января 2014

Это способ сделать это:

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
3 голосов
/ 15 марта 2012

Вот еще одно альтернативное решение, которое было объединено с другими решениями плюс peek ().

Без Peek () я столкнулся с тем, что приложение не вернулось бы без ctrl-c в конце при выполнении «type t.txt | prog.exe», где t.txt - многострочный файл. Но просто "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;
    }
}
2 голосов
/ 14 октября 2008

Console.In - это ссылка на TextReader, обернутый вокруг стандартного потока ввода. При передаче больших объемов данных в вашу программу таким способом может быть проще работать.

1 голос
/ 28 января 2010

проблема с предоставленным примером.

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

застрянет в ожидании ввода, если программа была запущена без переданных данных. поэтому пользователь должен вручную нажать любую клавишу для выхода из программы.

0 голосов
/ 27 октября 2017

Это также будет работать для

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);

    }
}
...