为什么.NET Core在Raspbian上对ReadKey的处理方式不同? [英] Why is .NET Core handling ReadKey differently on Raspbian?

查看:102
本文介绍了为什么.NET Core在Raspbian上对ReadKey的处理方式不同?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写.NET Core控制台应用程序。我想将控制台输入限制为每个输入一定数量的最大字符。我有一些代码通过使用 Console.ReadKey()而不是 Console.ReadLine()构造一个字符串来完成此操作在Windows上进行测试,一切工作正常。然后,当我部署到运行Raspbian的Raspberry Pi 3时,我很快遇到了各种各样的问题。我记得Linux处理行尾的方式与Windows不同,并且似乎退格键的处理方式也不同。我改变了处理这些字符的方式,取消了ConsoleKey而不是字符,换行符问题消失了,但是有时仅退格。另外,有时即使我将ReadKey设置为不单独输出到控制台,字符也会在输入框之外输出到控制台。我是否缺少有关Linux如何处理控制台输入的信息?

I'm writing a .NET Core console application. I wanted to limit console input to a certain number of maximum characters for each input. I have some code that does this by building a string with Console.ReadKey() instead of Console.ReadLine() Everything worked perfectly testing it on Windows. Then, when I deployed to a Raspberry Pi 3 running Raspbian, I quickly encountered all sorts of problems. I remembered that Linux handles line endings differently from Windows, and it seems backspaces are handled differently as well. I changed the way I handled those, going off the ConsoleKey instead of the character, and the newline problem went away, but backspaces only sometimes register. Also, sometimes characters get outputted to the console outside of my input box, even though I set the ReadKey to not output to the console on its own. Am I missing something about how Linux handles console input?

//I replaced my calls to Console.ReadLine() with this. The limit is the
//max number of characters that can be entered in the console.
public static string ReadChars(int limit)
{
    string str = string.Empty; //all the input so far
    int left = Console.CursorLeft; //store cursor position for re-outputting
    int top = Console.CursorTop;
    while (true) //keep checking for key events
    {
        if (Console.KeyAvailable)
        {
            //true to intercept input and not output to console
            //normally. This sometimes fails and outputs anyway.
            ConsoleKeyInfo c = Console.ReadKey(true);
            if (c.Key == ConsoleKey.Enter) //stop input on Enter key
                break;
            if (c.Key == ConsoleKey.Backspace) //remove last char on Backspace
            {
                if (str != "")
                {
                     tr = str.Substring(0, str.Length - 1);
                }
            }
            else if (c.Key != ConsoleKey.Tab && str.Length < limit)
            {
                //don't allow tabs or exceeding the max size
                str += c.KeyChar;
            }
            else
            {
                //ignore tabs and when the limit is exceeded
                continue;
            }
            Console.SetCursorPosition(left, top);
            string padding = ""; //padding clears unused chars in field
            for (int i = 0; i < limit - str.Length; i++)
            {
                padding += " ";
            }
            //output this way instead
            Console.Write(str + padding);
        }
    }
    return str;
}


推荐答案

我认为基本问题是由Stephen Toub在此GitHub问题
的评论公开

I think the fundamental issue is exposed by Stephen Toub's comment in this GitHub issue:


您可能会想到一个事实,我们现在仅在ReadKey(intercept:true)调用期间禁用回显,因此在用户键入与您调用ReadKey(截取:true),即使您希望不会,也可能会回显该键,但不会丢失键击。

You may be thinking of the fact that we now only disable echo during a ReadKey(intercept: true) call, so in a race between the user typing and you calling ReadKey(intercept: true), the key might be echo'd even when you were hoping it wouldn't be, but you won't lose the keystroke.

这是冷舒适度,但准确。这是一场很难获胜的比赛。核心问题是Linux终端的工作方式与Windows控制台完全不同。它的运行方式更像1970年代的电传打字机。无论计算机是否在乎您键入的内容,您都敲打键盘,电传打字机只是回显您键入的内容,然后将其敲打在纸上。直到您按Enter键,然后计算机才开始滚动显示文本。

Which is cold comfort, but accurate. This is a race that is very hard to win. The core problem is that a Linux terminal works very differently from the Windows console. It operates much more like a teletype did back in the 1970s. You banged away on the keyboard, regardless if the computer was paying any attention to what you type, the teletype just echo-ed what you typed banging it out on paper. Until you press the Enter key, then the computer started cranking away at the text.

与Windows控制台完全不同,它要求程序具有对Windows的活动Read调用。

Very different from the Windows console, it requires the program to have an active Read call to echo any typed text.

因此,这与控制台api基本不匹配。它需要一个 Echo 属性,使您有希望正确执行此操作。因此,您可以在开始接受输入并自己处理回声之前将其设置为 false 。这仍然是一场比赛,但是至少您可以清除任何预键入的文本。

So this is a pretty fundamental mismatch with the console api. It needs an Echo property to give you any hope of doing this correctly. So you can set it to false before you start accepting input and take care of the echo yourself. It is still a race, but at least you have a shot at clearing any pre-typed text.

您现在唯一的不雅观的解决方法是禁用回声,然后再开始程序。要求您通过您的方法进行所有输入。

The only half-decent workaround you have now is to disable echo before you start your program. Requiring you to do all input through your method.

这篇关于为什么.NET Core在Raspbian上对ReadKey的处理方式不同?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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