在C#中检查标准输入 [英] Checking Standard Input in C#

查看:202
本文介绍了在C#中检查标准输入的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在写一个小命令行实用程序,其目的是解析另一个实用程序的输出。我希望它可以通过两种方式调用:

I'm writing a small command line utility whose purpose is to parse the output of another utility. I want it to be invokable in two ways:

c:\> myutility filewithoutput.txt

或者,

c:\> otherutility -args | myutility

因此,基本上,标准in或文件参数。我第一次尝试看起来像这样:

So, basically, standard in or a file argument. My first attempt at this looked like this:

TextReader reader;

if (args.Length > 1) {
    reader = new StreamReader(new FileStream(args[1], FileMode.Open));
} else {
    reader = Console.In;
}

Process(reader);

文件参数工作正常,管道输出从实用程序到我的实用程序工作正常,但如果你只是正常调用它(没有参数和没有管道数据),它挂起。

The file argument works fine, and piping the output from the utility to my utility works fine, but if you just invoke it normally (no arguments and no piped data), it hangs. Or, rather, it blocks on waiting to read from standard in.

我的第二个草稿看起来像这样:

My second draft looked like this:

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 修复了无输入问题,如果你尝试管道数据> _<

While KeyAvailable fixes the "no input" problem, it throws an exception if you try to pipe in data >_<

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 ,所以我的下一个草稿是:

The exception suggests I use Console.In.Peek, so my next draft is as such:

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);

但是,这有与第一次尝试相同的问题:它阻塞,寻找输入。 Argh!

However, this has the same problem as the first try: It blocks, looking for input. Argh!

我有遗漏吗?

Sidenote:I我知道参数 - 的意思是使用标准输入的约定。我将使用,如果没有其他方式。但是,肯定有一些方法来检测是否是控制台的标准。

Sidenote: I am aware of the convention of the argument "-" meaning "use standard input". I will use that if there's no other way. But, surely there's got to be some way of detecting if standard in is the console or not!

编辑:这里是最终版本,似乎做我需要: / p>

Here's the final version that seems to do what I need:

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);

不是像这样使用流的异常,但是... eh。

Not a big fan of using Exceptions for flow like that, but... eh.

推荐答案

我一直在使用Pieter的解决方案,直到我意识到它在Mono中不起作用。当用管道输入检索 Console.KeyAvailable 时,Mono不会引发异常。因此,这种方法没有帮助。

I've been using Pieter's solution for a while until I realised it doesn't work in Mono. Mono doesn't throw an exception when retrieving Console.KeyAvailable with piped input, so that approach doesn't help.

但是,从.NET 4.5开始, Console 实际上提供了一个新的字段 IsInputRedirected 删除阴影和不必要的 try / catch

However, as of .NET 4.5, Console actually provides a new field IsInputRedirected which makes this a lot simpler, removes the obscurity and the unnecessary 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);

这篇关于在C#中检查标准输入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆