【问题标题】:Checking Standard Input in C#在 C# 中检查标准输入
【发布时间】:2011-04-27 01:37:52
【问题描述】:

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

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

文件参数可以正常工作,并且将实用程序的输出通过管道传输到我的实用程序也可以正常工作,但是如果您只是正常调用它(没有参数也没有管道数据),它就会挂起。或者,更确切地说,它会阻止等待从标准输入中读取。

我的第二稿是这样的:

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

不太喜欢使用异常处理这样的流程,但是...嗯。

【问题讨论】:

  • @bzlm - 为什么不直接链接到源代码(恰好是 Stack Overflow):stackoverflow.com/questions/3453220
  • @John 哦,所以我输入的搜索词没有排名最高是 my 的错。 :)
  • @bzlm - 绝对是 SE 的错,不是你的错!
  • 我会接受 Pieter 的回答,因为它可能更便携(不是说便携性是一个因素,但你永远不知道)。不过,不错的收获。

标签: c# .net console stdin


【解决方案1】:

快速而肮脏的方法是将 Console.KeyAvailable 包装在 try/catch 中,如果抛出,您就知道输入是从文件重定向的。当您找不到合适的方法为您进行检查时,使用 try/catch 来检测状态并不罕见。

【讨论】:

  • ...当答案如此明显时,我真的很讨厌它,它们从我身边飞过。不过,我仍然不喜欢没有内置方法可以做到这一点的事实......
  • 不幸的是,这似乎不适用于 Mono,but as of .NET 4.5 there's a simpler solution
【解决方案2】:

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

但是,从 .NET 4.5 开始,Console 实际上提供了一个新字段 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);

【讨论】:

  • 仅仅 5 年后重新审视这个问题,这听起来像是新的正确答案。酷!
【解决方案3】:

看起来您应该能够使用一些 Windows API 调用来确定这一点。 Hans Passant's answer 甚至还有一个辅助类来包装它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-31
    • 1970-01-01
    • 1970-01-01
    • 2012-04-25
    • 2019-11-15
    • 1970-01-01
    • 1970-01-01
    • 2015-10-02
    相关资源
    最近更新 更多