簡體   English   中英

檢查C#中的標准輸入

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM