La console C # riceve l'input con pipe
Domanda
So programmare l'applicazione Console con parametri, esempio: myProgram.exe param1 param2.
La mia domanda è: come posso far funzionare il mio programma con |, esempio: echo " word " | MyProgram.EXE?
Soluzione
Devi usare Console.Read()
e Console.ReadLine()
come se stessi leggendo l'input dell'utente. I tubi sostituiscono l'input dell'utente in modo trasparente. Non puoi usarli entrambi facilmente (anche se sono sicuro che sia del tutto possibile ...).
Modifica
Un semplice programma di stile cat
:
class Program
{
static void Main(string[] args)
{
string s;
while ((s = Console.ReadLine()) != null)
{
Console.WriteLine(s);
}
}
}
E quando eseguito, come previsto, l'output:
C:\...\ConsoleApplication1\bin\Debug>echo "Foo bar baz" | ConsoleApplication1.exe "Foo bar baz" C:\...\ConsoleApplication1\bin\Debug>
Altri suggerimenti
Quanto segue non sospenderà la richiesta di input e funzionerà quando i dati sono o non inviati. Un po 'di un trucco; e a causa dell'errore che intercetta, le prestazioni potrebbero mancare quando vengono effettuate numerose chiamate in pipe ma ... facile.
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
}
in .NET 4.5 è
if (Console.IsInputRedirected)
{
using(stream s = Console.OpenStandardInput())
{
...
Questo è il modo di farlo:
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);
}
}
Ciò consente due metodi di utilizzo. Leggi da input standard :
C:\test>myProgram.exe
hello
Data read was hello
o letto da input convogliato :
C:\test>echo hello | myProgram.exe
Data read was hello
Ecco un'altra soluzione alternativa che è stata messa insieme dalle altre soluzioni più una sbirciatina ().
Senza Peek () stavo sperimentando che l'app non sarebbe tornata senza ctrl-c alla fine quando facevo " digita t.txt | PROG.EXE quot &; dove t.txt è un file multilinea. Ma solo & Quot; prog.exe & Quot; oppure " echo hi | PROG.EXE quot &; ha funzionato bene.
questo codice ha lo scopo di elaborare solo input convogliato.
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 è un riferimento a un TextReader racchiuso nel flusso di input standard. Quando esegui il piping di grandi quantità di dati al tuo programma, potrebbe essere più semplice lavorare in questo modo.
si è verificato un problema con l'esempio fornito.
while ((s = Console.ReadLine()) != null)
resterà bloccato in attesa di input se il programma è stato avviato senza dati di piping. quindi l'utente deve premere manualmente un tasto qualsiasi per uscire dal programma.
Questo funzionerà anche per
c: \ MyApp.exe < input.txt
Ho dovuto usare StringBuilder per manipolare gli input catturati da 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);
}
}