Консоль C # принимает входные данные с помощью канала
Вопрос
Я знаю, как запрограммировать консольное приложение с параметрами, например :myProgram.exe парам1, парам2.
Мой вопрос в том, как я могу заставить свою программу работать с |, example :эхо "слова" | myProgram.exe ?
Решение
Вам нужно использовать 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>
Другие советы
Следующее не будет приостанавливать приложение для ввода и работает, когда данные или не переданы по конвейеру. Немного взломать; и из-за перехвата ошибок может произойти снижение производительности при выполнении многочисленных вызовов по каналу, но ... это просто.
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 Quot &; где t.txt - многострочный файл. Но просто & Quot; prog.exe & Quot; или " echo hi | prog.exe Quot &; работал нормально.
этот код предназначен только для обработки вводимых по трубопроводу данных.
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);
}
}