Piszę aplikację konsoli .NET Core. Chciałem ograniczyć wejście konsoli do pewnej liczby znaków maksymalnych dla każdego wejścia. Mam kod, który to robi, budując ciąg z Console.ReadKey()
zamiast Console.ReadLine()
Wszystko działało doskonale testowanie go w systemie Windows. Następnie, kiedy wdrożyłem Raspberry Pi 3 z Raspbian, szybko napotkałem różnego rodzaju problemy. Przypomniałem sobie, że Linux obsługuje końcówki linii inaczej niż Windows, i wygląda na to, że backspace są również obsługiwane inaczej. Zmieniłem sposób, w jaki sobie z nimi poradziłem, wychodząc z Konsolowego klucza zamiast postaci, a problem z nową linią zniknął, ale cofają się tylko czasy. Ponadto, czasami znaki są wysyłane do konsoli poza polem wprowadzania, mimo że ustawiam ReadKey, aby nie był wyprowadzany na konsolę samodzielnie. Czy brakuje mi czegoś o tym, jak Linux obsługuje wejście konsoli?Dlaczego .NET Core traktuje ReadKey inaczej na Raspbian?
//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;
}
Jest to * terminal *, który obsługuje naciśnięcia klawiszy. Nie dostaniesz żadnych klawiszy, które nie zostaną wysłane do Twojej aplikacji. Newlines nie mają z tym nic wspólnego. .NET (i Core) użyje ustawień systemu operacyjnego. Poza tym już rozpoznaje '\ n' jako znak nowej linii w Windows –
Windows rozpoznaje znaki powrotu karetki,' \ r', podczas gdy Linux po prostu używa znaków nowej linii, '\ n'. Początkowo sprawdzałem "\ r", co oczywiście doprowadziło do problemów. Próbowałem dowiedzieć się, czy nie istnieją inne różnice, o których nie mówię. Pomyślałem, że sugeruje, że musi to wynikać z różnic w sposobie obsługi klawiszy przez terminal. Chodzi mi tylko o to, że połączenia z ReadKey dają różne wyniki na różnych komputerach, nawet jeśli wykonuję dokładnie te same naciśnięcia klawiszy, nie ma wątpliwości z powodu sposobu, w jaki różne systemy przetwarzają te klawisze. – tyjkenn
Nie jestem pewien, jak to wszystko ma sens. W systemie Linux nadal naciskasz klawisz Enter, nie naciskaj klawisza Ctrl + J, aby uzyskać \ n. ReadKey powie ci o naciśniętym klawiszu, a nie o tym, jaki ma postać. Dopóki używasz Key, a nie KeyChar, nie powinno być problemu. Być może naraziłeś się na problem kompatybilności, to wszystko jest całkiem nowe, więc nie jest to nie do pomyślenia. Obsługują około dziesięciu różnych smaków Linuksa, a Raspian nie jest jednym z nich. Najlepiej im o tym powiedzieć, użyj przycisku [New Issue] (https://github.com/dotnet/coreclr/issues). –