Я знаю, как программировать консольное приложение с параметрами, например: myProgram.exe param1 param2.
Мой вопрос: как я могу заставить свою программу работать с |, например: echo "word" | myprogram.exe?
Я знаю, как программировать консольное приложение с параметрами, например: myProgram.exe param1 param2.
Мой вопрос: как я могу заставить свою программу работать с |, например: echo "word" | myprogram.exe?
Вам нужно использовать 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>
Следующее не приостанавливает приложение для ввода и работает, когда данные передаются или не передаются по каналам. Немного взлома; и из-за сбоя при ошибках производительность может отсутствовать, когда совершаются многочисленные вызовы с помощью телефонной трубки, но... легко.
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
}
в .NET 4.5 это
if (Console.IsInputRedirected)
{
using(stream s = Console.OpenStandardInput())
{
...
Это способ сделать это:
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
Вот еще одно альтернативное решение, которое было собрано вместе с другими решениями плюс 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;
}
}
Console.In - ссылка на TextReader, обернутую вокруг стандартного входного потока. При передаче больших объемов данных в вашу программу может быть проще работать с этим способом.
есть проблема с приведенным примером.
while ((s = Console.ReadLine()) != null)
застрянет в ожидании ввода, если программа была запущена без данных с каналами. поэтому пользователю необходимо вручную нажать любую клавишу для выхода из программы.
Это также будет работать для
c:\MyApp.exe < input.txt
Мне пришлось использовать 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);
}
}