2017-10-09 7 views
8

मैं एक .NET कोर कंसोल एप्लिकेशन लिख रहा हूं। मैं प्रत्येक इनपुट के लिए अधिकतम वर्णों की एक निश्चित संख्या में कंसोल इनपुट को सीमित करना चाहता था। मेरे पास कुछ कोड है जो Console.ReadLine() के बजाय Console.ReadKey() के साथ एक स्ट्रिंग बनाकर ऐसा करता है सबकुछ विंडोज पर पूरी तरह से परीक्षण करता है। फिर, जब मैंने रास्पबेरी पाई 3 को रास्पियन चलाने के लिए तैनात किया, तो मुझे जल्दी ही सभी प्रकार की समस्याओं का सामना करना पड़ा। मुझे याद आया कि लिनक्स विंडोज़ से अलग-अलग लाइन अंतराल को संभालता है, और ऐसा लगता है कि बैकस्पेस को अलग-अलग संभाला जाता है। मैंने उन तरीकों को बदल दिया जिन्हें मैंने चरित्र के बजाए कंसोलकी से बाहर कर दिया, और नई लाइन समस्या दूर हो गई, लेकिन बैकस्पेस केवल कभी-कभी पंजीकरण करते थे। साथ ही, कभी-कभी वर्ण मेरे इनपुट बॉक्स के बाहर कंसोल पर आउटपुट हो जाते हैं, भले ही मैंने रीडकी को कंसोल पर आउटपुट न करने के लिए सेट किया हो। क्या मैं कुछ याद कर रहा हूं कि लिनक्स कंसोल इनपुट कैसे संभालता है?राइटबियन पर .NET कोर हैंडलिंग रीडकी अलग-अलग क्यों है?

//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; 
} 
+0

यह * टर्मिनल * है जो कीस्ट्रोक को संभालता है। आपको कोई भी कुंजीस्ट्रोक नहीं मिलेगा जो आपके आवेदन पर पहले स्थान पर नहीं भेजे जाते हैं। न्यूलाइन के पास इसके साथ कुछ लेना देना नहीं है। .NET (और कोर) ऑपरेटिंग सिस्टम की सेटिंग्स का उपयोग करेगा। इसके अलावा, यह पहले से ही विंडोज़ –

+0

में एक नई लाइन के रूप में '\ n' को पहचानता है, विंडोज़ कैरिज रिटर्न कैरेक्टर, \ r' को पहचानता है, जबकि लिनक्स केवल न्यूलाइन अक्षरों का उपयोग करता है, \ n'। मैं मूल रूप से '\ r' की जांच कर रहा था, जिसने निश्चित रूप से समस्याओं का सामना किया। मैं यह पता लगाने की कोशिश कर रहा था कि क्या ऐसे अन्य मतभेद थे जिनके लिए मैं लेखांकन नहीं कर रहा हूं। मैंने सोचा कि यह निहित था कि टर्मिनल कीस्ट्रोक को कैसे नियंत्रित करता है इसमें अंतर के साथ यह होना चाहिए। मेरा मुद्दा यह था कि रीडकी को अलग-अलग मशीनों पर अलग-अलग परिणाम मिलते हैं, भले ही मैं सटीक एक ही कीस्ट्रोक करता हूं, इस बात पर शक नहीं कि अलग-अलग सिस्टम उन कीस्ट्रोक को कैसे संसाधित करते हैं। – tyjkenn

+4

इतना सुनिश्चित नहीं है कि इनमें से कोई भी समझ में आता है। लिनक्स पर आप अभी भी एंटर कुंजी दबाते हैं, आप \ n प्राप्त करने के लिए Ctrl + J दबाएं नहीं। ReadKey आपको दबाए गए कुंजी के बारे में बताता है, न कि यह कौन सा चरित्र पैदा करता है। तो जब तक आप कुंजी का उपयोग करते हैं और KeyChar नहीं तो तब तक कोई समस्या नहीं होनी चाहिए। हो सकता है कि आपने एक संगतता समस्या का खुलासा किया, यह सब बिल्कुल नया है इसलिए यह असंभव नहीं है। और वे दस अलग-अलग लिनक्स स्वादों का समर्थन करते हैं और रास्पियन उनमें से एक नहीं है। इसके बारे में बताने के लिए सर्वश्रेष्ठ, [नया अंक बटन] (https://github.com/dotnet/coreclr/issues) का उपयोग करें। –

उत्तर

2

मैं मौलिक मुद्दा this GitHub issue में स्टीफन Toub की टिप्पणी से सामने आ रहा है लगता है:

आप हो सकता है इस तथ्य के बारे में सोचते हुए कि अब हम केवल रीडकी (अवरोध: सत्य) कॉल के दौरान गूंज अक्षम करते हैं, इसलिए उपयोगकर्ता टाइपिंग के बीच की दौड़ में और आप रीडकी (अवरोध: सत्य) को कॉल करते हैं, तो जब भी आप उम्मीद कर रहे थे तब भी कुंजी गूंज सकती है यह नहीं होगा, लेकिन आप कीस्ट्रोक खोना नहीं होगा।

जो ठंडा आराम है, लेकिन सटीक है। यह एक ऐसी दौड़ है जो जीतना बहुत मुश्किल है। मुख्य समस्या यह है कि एक लिनक्स टर्मिनल विंडोज कंसोल से बहुत अलग तरीके से काम करता है। यह 1 9 70 के दशक में टेलेटाइप की तरह बहुत अधिक काम करता है।आपने कुंजीपटल पर टक्कर लगी, भले ही कंप्यूटर आपके द्वारा टाइप किए जाने वाले किसी भी ध्यान पर ध्यान दे रहा हो, टेलेटाइप सिर्फ उस चीज को प्रतिबिंबित करता है जिसे आपने पेपर पर बैंग कर दिया था। जब तक आप एंटर कुंजी दबाएंगे, तब तक कंप्यूटर ने टेक्स्ट पर क्रैंकिंग शुरू कर दी।

विंडोज कंसोल से बहुत अलग है, इसके लिए प्रोग्राम को सक्रिय टाइप करने की आवश्यकता है किसी भी टाइप किए गए टेक्स्ट को गूंजने के लिए कॉल पढ़ें।

तो यह कंसोल एपीआई के साथ एक सुंदर मौलिक मेल नहीं है। आपको इसे सही तरीके से करने की कोई आशा देने के लिए Echo संपत्ति की आवश्यकता है। इसलिए आप इसे इनपुट स्वीकार करना शुरू करने से पहले झूठी पर सेट कर सकते हैं और स्वयं को गूंजने का ख्याल रख सकते हैं। यह अभी भी एक दौड़ है, लेकिन कम से कम आपके पास किसी भी प्री-टाइप किए गए टेक्स्ट को साफ़ करने पर एक शॉट है।

आपके प्रोग्राम को शुरू करने से पहले आपके पास अब केवल आधा सभ्य कामकाज disable echo है। आपको अपनी विधि के माध्यम से सभी इनपुट करने की आवश्यकता है।

+0

सौभाग्य से मेरे लिए, उस विधि के माध्यम से मेरे सभी इनपुट को चलाने के लिए पूरी तरह से ठीक है, इसलिए मैं इस कामकाज को "आधा सभ्य" से थोड़ा अधिक मानता हूं। धन्यवाद! – tyjkenn

2

मैं परीक्षण किया है और पता चला कि Console.ReadKey(true) वास्तव में कुछ कीड़े जहां कुंजी वास्तव में कंसोल के लिए गूँजती हो जाता है जब टाइपिंग तेज है या दोहराने कुंजी निकाल दिया जाता है। यह ऐसा कुछ है जिसे आप उम्मीद नहीं करते हैं, लेकिन ऐसा क्यों होता है मुझे कोई जानकारी नहीं है।

आप इसे डिबगिंग में रुचि रखते हैं, तो आप नीचे स्रोत कोड

https://referencesource.microsoft.com/#mscorlib/system/console.cs,1476

मैं इस मुद्दे के लिए एक समाधान डाल करने के लिए चुना है देख सकते हैं। तो आपके दृष्टिकोण में कुछ मुद्दे हैं। Left Arrow और Right Arrow कुंजी को संभाला जाना चाहिए या उन्हें अनुमति नहीं दी जानी चाहिए। आप नीचे दिए गए

Console.Write(str + padding); 

का उपयोग कर आप मूल रूप से भी कर्सर की स्थिति है, जो सही नहीं है परेशान वर्ण लिखने जब मैं कोड

if (c.Key == ConsoleKey.LeftArrow || c.Key == ConsoleKey.RightArrow) { 
    continue; 
} 

नीचे जोड़कर बाद में एक चुना है। तो आप नीचे दिए गए

Console.CursorLeft = str.Length; 

का उपयोग कर इस के बाद कर्सर की स्थिति निर्धारित करने की आवश्यकता अब टपकाया कुंजी है जो शायद एक .NET बग है से निपटने के हिस्से आता है, मैं कोड के नीचे जोड़ा

else 
{ 
    //ignore tabs and when the ilimit is exceeded 
    if (Console.CursorLeft > str.Length){ 

     var delta = Console.CursorLeft - str.Length; 
     Console.CursorLeft = str.Length; 
     Console.Write(new String(' ',delta)); 
     Console.CursorLeft = str.Length; 
    } 
    continue; 
} 

तो हम जाँच किसी भी अदृश्य कारण के लिए कुछ गूंज लिया गया था, फिर इसे मिटा दें। फिर तनाव इसका परीक्षण किया

$ docker run -it console 
Please enter some text: 
tarun6686e 
You entered: tarun6686e 

नीचे अंतिम कोड है कि मैं का इस्तेमाल किया था

using System; 

namespace ConsoleTest 
{ 
    public class Program { 
     public static string tr=""; 
     //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); 
        string name = Enum.GetName(typeof(ConsoleKey), c.Key); 
        var key = c.KeyChar; 
        // Console.WriteLine(String.Format("Name={0}, Key={1}, KeyAscii={2}", name, key,(int)key)); 
        if (c.Key == ConsoleKey.Enter) //stop input on Enter key 
         { 
          Console.WriteLine(); 
          break; 
         } 
        if (c.Key == ConsoleKey.LeftArrow || c.Key == ConsoleKey.RightArrow) { 
         continue; 
        } 

        if (c.Key == ConsoleKey.Backspace) //remove last char on Backspace 
        { 
         if (str != "") 
         { 
          str = 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 ilimit is exceeded 
         if (Console.CursorLeft > str.Length){ 

          var delta = Console.CursorLeft - str.Length; 
          Console.CursorLeft = str.Length; 
          Console.Write(new String(' ',delta)); 
          Console.CursorLeft = str.Length; 
         } 
         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); 
        Console.CursorLeft = str.Length; 
       } 
      } 
      return str; 
     } 

     public static void Main(string[] args) { 
      Console.WriteLine("Please enter some text: "); 
      var text = ReadChars(10); 

      Console.WriteLine("You entered: " + text); 
     } 
    } 
} 
+0

खराब लिंक, आपको .NETCore में कंसोल के यूनिक्स-विशिष्ट स्वाद की आवश्यकता है। मुझे लगता है कि यह [यह एक है] (https://github.com/dotnet/corefx/blob/master/src/System.Console/src/System/ConsolePal.Unix.cs)। सुंदर निर्दोष लग रहा है। शायद बहुत निर्दोष :) –

+0

सुधार @ हंसपैसेंट के लिए धन्यवाद, मुझे .NET कोर कोडबेस –

+0

को देखने की आवश्यकता महसूस नहीं हुई, इस कोड के साथ गड़बड़ करने के बाद, मैं इस दृष्टिकोण को काम करने में कामयाब रहा। हालांकि, मेरे कार्यक्रम के दूसरे हिस्से में जहां मैं एक और तरीके से कीबोर्ड इनपुट का उपयोग कर रहा हूं (पृष्ठों के माध्यम से फ़्लिप करने के लिए), मैं कुछ कुंजियां नहीं पकड़ सका, जबकि पूरे कंसोल को फिर से खींचा जा रहा था। आखिरकार, मुझे गूंज अक्षम करना पड़ा। – tyjkenn