[英]Checking Standard Input in C#
我正在編寫一個小命令行實用程序,其目的是解析另一個實用程序的輸出。 我希望它可以通過兩種方式調用:
c:\> myutility filewithoutput.txt
要么,
c:\> otherutility -args | myutility
所以,基本上,標准或文件參數。 我對此的第一次嘗試看起來像這樣:
TextReader reader;
if (args.Length > 1) {
reader = new StreamReader(new FileStream(args[1], FileMode.Open));
} else {
reader = Console.In;
}
Process(reader);
file參數工作正常,將實用程序的輸出傳遞給我的實用程序工作正常,但如果你只是正常調用它(沒有參數和沒有管道數據),它就會掛起。 或者說,它阻止等待從標准讀取。
我的第二稿看起來像這樣:
TextReader reader;
if (args.Length > 1) {
reader = new StreamReader(new FileStream(args[1], FileMode.Open));
} else {
if(Console.KeyAvailable) {
reader = Console.In;
} else {
Console.WriteLine("Error, need data");
return;
}
}
Process(reader);
雖然KeyAvailable
修復了“無輸入”問題,但如果您嘗試管道數據> _ <,則會引發異常
Unhandled Exception: System.InvalidOperationException: Cannot see if a key
has been pressed when either application does not have a console or when
console input has been redirected from a file. Try Console.In.Peek.
at System.Console.get_KeyAvailable()
at MyUtility.Program.Main(String[] args) in Program.cs:line 39
例外建議我使用Console.In.Peek
,所以我的下一個草案是這樣的:
TextReader reader;
if (args.Length > 1) {
reader = new StreamReader(new FileStream(args[1], FileMode.Open));
} else {
if(Console.In.Peek() != 0) {
reader = Console.In;
} else {
Console.WriteLine("Error, need data");
return;
}
}
Process(reader);
但是,這與第一次嘗試有同樣的問題:它阻塞,尋找輸入。 哎呀!
有什么我想念的嗎?
旁注:我知道參數“ - ”的約定意味着“使用標准輸入”。 如果沒有別的辦法,我會用它。 但是,肯定有一些方法可以檢測標准輸入是否是控制台!
編輯:這是最終版本似乎做我需要的:
TextReader reader;
if (args.Length > 1) {
reader = new StreamReader(new FileStream(args[1], FileMode.Open));
} else {
try {
bool tmp = Console.KeyAvailable;
Console.WriteLine("Error, need data");
return;
} catch(InvalidOperationException) {
reader = Console.In;
}
}
Process(reader);
不像那樣使用Exceptions for flow,但是......呃。
快速而又臟的方法是將Console.KeyAvailable包裝在try / catch中,如果拋出,則表示輸入是從文件重定向的。 當您找不到合適的方法來檢查狀態時,使用try / catch檢測狀態並不是很常見。
我一直在使用Pieter的解決方案,直到我意識到它在Mono中不起作用。 使用管道輸入檢索Console.KeyAvailable
時,Mono不會拋出異常,因此該方法無效。
但是,從.NET 4.5開始, Console
實際上提供了一個新的字段IsInputRedirected
,這使得這更簡單,刪除了IsInputRedirected
和不必要的try
/ catch
:
TextReader reader;
if (args.Length > 1) {
reader = new StreamReader(new FileStream(args[1], FileMode.Open));
} else {
if (Console.IsInputRedirected) {
reader = Console.In;
} else {
Console.WriteLine("Error, need data");
return;
}
}
Process(reader);
看起來您應該能夠使用一些Windows API調用來確定它。 Hans Passant的答案甚至還有一個輔助課程來包裝它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.