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

查看:22
本文介绍了为什么 .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(intercept: true) 之间的竞争中,关键可能是 echo'd 即使您希望它不会,但您不会丢失按键.

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 控制台非常不同,它要求程序有一个活动的 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.

您现在唯一还算不错的解决方法是 在启动程序之前禁用 echo.要求您通过您的方法进行所有输入.

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天全站免登陆