मैं C # विंडोज कंसोल ऐप में करंट लाइन को कैसे अपडेट कर सकता हूं?


507

जब C # में एक Windows कंसोल ऐप का निर्माण किया जाता है, तो क्या कंसोल को बिना किसी मौजूदा लाइन का विस्तार किए या एक नई लाइन पर जाने के लिए लिखना संभव है? उदाहरण के लिए, अगर मैं एक प्रतिशत दिखाना चाहता हूं कि प्रक्रिया पूरी होने के करीब है, तो मैं कर्सर के समान लाइन पर मान को अपडेट करना चाहता हूं, और प्रत्येक प्रतिशत को नई लाइन पर नहीं रखना है।

क्या यह "मानक" C # कंसोल ऐप के साथ किया जा सकता है?


यदि आप वास्तव में शांत कमांड लाइन इंटरफेस में रुचि रखते हैं तो आपको शाप / ncurses की जांच करनी चाहिए।
चार्ल्स एडिस

@CharlesAddis लेकिन शाप / ncurses केवल C ++ में काम नहीं करता है?
Xam

जवाबों:


783

यदि आप केवल "\r"कंसोल पर प्रिंट करते हैं तो कर्सर वर्तमान लाइन की शुरुआत में वापस चला जाता है और फिर आप इसे फिर से लिख सकते हैं। यह काम कर जाना चाहिए:

for(int i = 0; i < 100; ++i)
{
    Console.Write("\r{0}%   ", i);
}

संख्या के बाद कुछ रिक्त स्थान पर ध्यान दें कि यह सुनिश्चित करने के लिए कि पहले जो कुछ भी था वह मिटा दिया गया है।
इसके Write()बजाय इसके उपयोग पर ध्यान दें WriteLine()क्योंकि आप पंक्ति के अंत में एक "\ n" जोड़ना नहीं चाहते हैं।


7
for (int i = 0; मैं <= 100; ++ i) 100% तक जाऊंगा
निकोलस टायलर

13
जब आप पिछला लेखन नए लेखन की तुलना में लंबा था, तो आप कैसे संभालेंगे? क्या कंसोल की चौड़ाई प्राप्त करने और रिक्त स्थान के साथ लाइन को पैड करने का कोई तरीका है, हो सकता है?
आकर्षित चैपिन

6
@druciferre मेरे सिर के ऊपर से मैं आपके प्रश्न के दो उत्तर सोच सकता हूं। वे दोनों वर्तमान आउटपुट को एक स्ट्रिंग के रूप में सहेजना शामिल करते हैं और इसे इस तरह के वर्णों की एक निर्धारित मात्रा के साथ पेडिंग करते हैं: Console.Write ("\ r {0}", strOutput.PadRight (nPaddingCount, '')); "NPaddingCount" एक ऐसी संख्या हो सकती है जिसे आप स्वयं सेट करते हैं या आप पिछले आउटपुट का ट्रैक रख सकते हैं और nPaddingCount को पिछले और वर्तमान आउटपुट के बीच की लंबाई और वर्तमान आउटपुट लंबाई के बीच के अंतर के रूप में सेट कर सकते हैं। यदि nPaddingCount निगेटिव है तो आपको PadRight का उपयोग नहीं करना होगा जब तक कि आप abs (prev.len - curr.len) नहीं करते।
जॉन ओडोम

1
@malgm सुव्यवस्थित कोड। यदि कोई एक दर्जन सूत्र कभी भी सांत्वना के लिए लिख सकते थे, तो यह आपको परेशान कर देगा कि चाहे आप नई लाइनें लिख रहे हों या नहीं।
मार्क

2
@JohnOdom आपको केवल पिछली (अनपैडेड) आउटपुट लंबाई रखने की आवश्यकता है, और फिर पहले तर्क के रूप में PadRight(अनपेड स्ट्रिंग, या लंबाई, पहले, निश्चित रूप से) को बचाने के लिए फीड करें ।
जेस्पर मैथिसन

254

आप Console.SetCursorPositionकर्सर की स्थिति निर्धारित करने के लिए उपयोग कर सकते हैं और फिर वर्तमान स्थिति पर लिख सकते हैं।

यहाँ एक उदाहरण "स्पिनर" दिखाया गया है:

static void Main(string[] args)
{
    var spin = new ConsoleSpinner();
    Console.Write("Working....");
    while (true) 
    {
        spin.Turn();
    }
}

public class ConsoleSpinner
{
    int counter;

    public void Turn()
    {
        counter++;        
        switch (counter % 4)
        {
            case 0: Console.Write("/"); counter = 0; break;
            case 1: Console.Write("-"); break;
            case 2: Console.Write("\\"); break;
            case 3: Console.Write("|"); break;
        }
        Thread.Sleep(100);
        Console.SetCursorPosition(Console.CursorLeft - 1, Console.CursorTop);
    }
}

ध्यान दें कि आपको किसी भी मौजूदा आउटपुट को नए आउटपुट या ब्लॉक्स के साथ ओवरराइट करना सुनिश्चित करना होगा।

अद्यतन: जैसा कि यह आलोचना की गई है कि उदाहरण कर्सर को केवल एक वर्ण द्वारा वापस ले जाता है, मैं इसे स्पष्टीकरण के लिए जोड़ूंगा: SetCursorPositionआप कर्सर को कंसोल विंडो में किसी भी स्थिति में सेट कर सकते हैं।

Console.SetCursorPosition(0, Console.CursorTop);

वर्तमान लाइन की शुरुआत में कर्सर सेट करेगा (या आप Console.CursorLeft = 0सीधे उपयोग कर सकते हैं )।


8
समस्या को हल किया जा सकता है \ r का उपयोग करके, लेकिन SetCursorPosition(या CursorLeft) अधिक लचीलेपन की अनुमति देता है, जैसे कि लाइन की शुरुआत में लिखना नहीं, खिड़की में ऊपर जाना, आदि। इसलिए यह एक अधिक सामान्य दृष्टिकोण है जिसका उपयोग उदा आउटपुट के लिए किया जा सकता है कस्टम प्रगति बार या ASCII ग्राफिक।
डर्क वोल्मार

14
+1 क्रिया के लिए और ड्यूटी के कॉल से ऊपर और आगे जाने के लिए। अच्छा सामान धन्यवाद।
कोपा

1
इसे करने का एक अलग तरीका दिखाने के लिए +1। अन्य सभी ने \ r दिखाया, और यदि ओपी केवल एक प्रतिशत अपडेट कर रहा है, तो इसके साथ वह पूरी लाइन को फिर से लिखने के बिना मूल्य को अपडेट कर सकता है। ओपी ने वास्तव में कभी नहीं कहा कि वह लाइन की शुरुआत में जाना चाहता था, बस वह कर्सर के समान लाइन पर कुछ अपडेट करना चाहता था।
एंडी

1
SetCursorPosition का जोड़ा लचीलापन थोड़ी गति और एक ध्यान देने योग्य कर्सर झिलमिलाहट की कीमत पर आता है अगर उपयोगकर्ता को नोटिस करने के लिए लूप काफी लंबा है। मेरी परीक्षा की टिप्पणी नीचे देखें।
केविन

5
यह भी पुष्टि करें कि लाइन की लंबाई कंसोल को अगली पंक्ति में लपेटने का कारण नहीं बनती है या आपको वैसे भी कंसोल विंडो के नीचे चल रही सामग्री के साथ समस्या हो सकती है।
मंडराके

84

अब तक हमारे पास यह करने के लिए तीन प्रतिस्पर्धी विकल्प हैं:

Console.Write("\r{0}   ", value);                      // Option 1: carriage return
Console.Write("\b\b\b\b\b{0}", value);                 // Option 2: backspace
{                                                      // Option 3 in two parts:
    Console.SetCursorPosition(0, Console.CursorTop);   // - Move cursor
    Console.Write(value);                              // - Rewrite
}

मैंने हमेशा उपयोग किया है Console.CursorLeft = 0, तीसरे विकल्प पर एक बदलाव, इसलिए मैंने कुछ परीक्षण करने का फैसला किया। यहाँ मैं उपयोग किया गया कोड है:

public static void CursorTest()
{
    int testsize = 1000000;

    Console.WriteLine("Testing cursor position");
    Stopwatch sw = new Stopwatch();
    sw.Start();
    for (int i = 0; i < testsize; i++)
    {
        Console.Write("\rCounting: {0}     ", i);
    }
    sw.Stop();
    Console.WriteLine("\nTime using \\r: {0}", sw.ElapsedMilliseconds);

    sw.Reset();
    sw.Start();
    int top = Console.CursorTop;
    for (int i = 0; i < testsize; i++)
    {
        Console.SetCursorPosition(0, top);        
        Console.Write("Counting: {0}     ", i);
    }
    sw.Stop();
    Console.WriteLine("\nTime using CursorLeft: {0}", sw.ElapsedMilliseconds);

    sw.Reset();
    sw.Start();
    Console.Write("Counting:          ");
    for (int i = 0; i < testsize; i++)
    {        
        Console.Write("\b\b\b\b\b\b\b\b{0,8}", i);
    }

    sw.Stop();
    Console.WriteLine("\nTime using \\b: {0}", sw.ElapsedMilliseconds);
}

मेरी मशीन पर, मुझे निम्नलिखित परिणाम मिलते हैं:

  • backspaces: 25.0 सेकंड
  • कैरिज रिटर्न: 28.7 सेकंड
  • SetCursorPosition: 49.7 सेकंड

इसके अतिरिक्त, SetCursorPositionध्यान देने योग्य झिलमिलाहट का कारण बनता है कि मैंने विकल्पों में से किसी के साथ निरीक्षण नहीं किया। इसलिए, नैतिक संभव होने पर बैकस्पेस या गाड़ी के रिटर्न का उपयोग करना है , और मुझे ऐसा करने का तेज़ तरीका सिखाने के लिए धन्यवाद , अतः!


अपडेट : टिप्पणियों में, जोएल ने सुझाव दिया कि सेटरकोर्सपॉन्जन स्थानांतरित दूरी के संबंध में स्थिर है, जबकि अन्य विधियां रैखिक हैं। इसके अलावा परीक्षण की पुष्टि करता है कि यह मामला है, हालांकि निरंतर समय और धीमी गति से अभी भी धीमी है। मेरे परीक्षणों में, कंसोल के लिए बैकस्पेस की एक लंबी स्ट्रिंग लिखना लगभग 60 वर्णों तक, SetCursorPosition की तुलना में तेज़ है। इसलिए बैकस्पेस 60 वर्णों (या तो) से छोटी रेखा के भागों को बदलने के लिए तेज़ है, और यह झिलमिलाहट नहीं करता है, इसलिए मैं अपने प्रारंभिक समर्थन के आधार पर \ b over \ r और SetCursorPosition


4
प्रश्न में ऑपरेशन की दक्षता वास्तव में मायने नहीं रखती है। उपयोगकर्ता को नोटिस करने के लिए यह सब बहुत तेजी से होना चाहिए। अनावश्यक माइक्रोएप्टिमेशन खराब है।
मालफिस्ट

@ मालफिस्ट: लूप की लंबाई के आधार पर, उपयोगकर्ता नोटिस कर सकता है या नहीं। जैसा कि मैंने ऊपर संपादन में जोड़ा (इससे पहले कि मैंने आपकी टिप्पणी देखी), SetCursorPosition ने झिलमिलाहट शुरू की और अन्य विकल्पों के रूप में लगभग दो बार लेता है।
केविन

1
मैं सहमत हूं कि यह एक माइक्रो-ऑप्टिमाइज़ेशन है (इसे एक लाख बार चलाना और 50 सेकंड लेना अभी भी बहुत कम समय है), परिणामों के लिए +1, और यह निश्चित रूप से जानना बहुत उपयोगी हो सकता है।
एंडी

6
बेंचमार्क मूलभूत रूप से त्रुटिपूर्ण है। यह संभव है कि SetCursorPosition () समय एक ही है चाहे कर्सर कितना भी आगे बढ़ जाए, जबकि अन्य विकल्पों में कितने वर्णों पर कंसोल को संसाधित करना होता है।
जोएल कोएहॉर्न

1
यह उपलब्ध विभिन्न विकल्पों में से एक बहुत अच्छा योग है। हालाँकि, मैं भी \ r का उपयोग करते समय टिमटिमाता हुआ देखता हूँ। \ B के साथ स्पष्ट रूप से कोई टिमटिमाता नहीं है क्योंकि फिक्स टेक्स्ट ("काउंटिंग:") फिर से नहीं लिखा गया है। यदि आप अतिरिक्त \ b जोड़ते हैं, तो आप फ़्लिकरिंग भी करेंगे और फिक्स टेक्स्ट को फिर से लिखेंगे क्योंकि यह \ b और SetCursorPosition के साथ हो रहा है। योएल की टिप्पणी के बारे में: जोएल मूल रूप से सही है, हालाँकि \ r अभी भी बहुत लंबी लाइनों पर SetCursorPosition को बेहतर बना देगा, लेकिन अंतर कम हो जाता है।
डर्क वोल्मार

27

आप \ b का उपयोग कर सकते हैं वर्तमान पंक्ति पर वर्णों की एक विशेष संख्या का बैकअप लेने के (बैकस्पेस) एस्केप अनुक्रम का । यह सिर्फ वर्तमान स्थान को स्थानांतरित करता है, यह पात्रों को नहीं हटाता है।

उदाहरण के लिए:

string line="";

for(int i=0; i<100; i++)
{
    string backup=new string('\b',line.Length);
    Console.Write(backup);
    line=string.Format("{0}%",i);
    Console.Write(line);
}

यहाँ, लाइन प्रतिशत लाइन कंसोल के लिए लिखने के लिए है। चाल पिछले आउटपुट के लिए सही संख्या में \ b वर्ण उत्पन्न करना है ।

इस \ r दृष्टिकोण से अधिक लाभ यह है कि अगर आपका प्रतिशत आउटपुट लाइन की शुरुआत में नहीं है तो भी काम करता है।


1
+1, यह प्रस्तुत की गई सबसे तेज़ विधि है (नीचे मेरी परीक्षण टिप्पणी देखें)
केविन

19

\rइन परिदृश्यों के लिए उपयोग किया जाता है।
\r एक गाड़ी वापसी का प्रतिनिधित्व करता है, जिसका अर्थ है कि कर्सर लाइन की शुरुआत में लौटता है।
यही कारण है कि विंडोज \n\rअपने नए लाइन मार्कर के रूप में उपयोग करता है।
\nआपको एक रेखा से नीचे ले जाता है, और \rआपको रेखा के आरंभ में लौटाता है।


22
सिवाय यह वास्तव में \ n \ n है।
जोएल मुलर

14

मुझे सिर्फ डिवो की ConsoleSpinnerक्लास के साथ खेलना था । खदान संक्षिप्त रूप में कहीं नहीं है, लेकिन यह मेरे साथ अच्छी तरह से नहीं बैठी है कि उस वर्ग के उपयोगकर्ताओं को अपना while(true)लूप लिखना है । मैं इस तरह से एक अनुभव के लिए शूटिंग कर रहा हूं:

static void Main(string[] args)
{
    Console.Write("Working....");
    ConsoleSpinner spin = new ConsoleSpinner();
    spin.Start();

    // Do some work...

    spin.Stop(); 
}

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

इसके अलावा, मैंने उस बहु-थ्रेडिंग को नहीं किया है इसलिए यह संभव है (संभावना है) कि मैंने एक सूक्ष्म बग या तीन को छोड़ दिया है। लेकिन यह अब तक बहुत अच्छा काम करता है:

public class ConsoleSpinner : IDisposable
{       
    public ConsoleSpinner()
    {
        CursorLeft = Console.CursorLeft;
        CursorTop = Console.CursorTop;  
    }

    public ConsoleSpinner(bool start)
        : this()
    {
        if (start) Start();
    }

    public void Start()
    {
        // prevent two conflicting Start() calls ot the same instance
        lock (instanceLocker) 
        {
            if (!running )
            {
                running = true;
                turner = new Thread(Turn);
                turner.Start();
            }
        }
    }

    public void StartHere()
    {
        SetPosition();
        Start();
    }

    public void Stop()
    {
        lock (instanceLocker)
        {
            if (!running) return;

            running = false;
            if (! turner.Join(250))
                turner.Abort();
        }
    }

    public void SetPosition()
    {
        SetPosition(Console.CursorLeft, Console.CursorTop);
    }

    public void SetPosition(int left, int top)
    {
        bool wasRunning;
        //prevent other start/stops during move
        lock (instanceLocker)
        {
            wasRunning = running;
            Stop();

            CursorLeft = left;
            CursorTop = top;

            if (wasRunning) Start();
        } 
    }

    public bool IsSpinning { get { return running;} }

    /* ---  PRIVATE --- */

    private int counter=-1;
    private Thread turner; 
    private bool running = false;
    private int rate = 100;
    private int CursorLeft;
    private int CursorTop;
    private Object instanceLocker = new Object();
    private static Object console = new Object();

    private void Turn()
    {
        while (running)
        {
            counter++;

            // prevent two instances from overlapping cursor position updates
            // weird things can still happen if the main ui thread moves the cursor during an update and context switch
            lock (console)
            {                  
                int OldLeft = Console.CursorLeft;
                int OldTop = Console.CursorTop;
                Console.SetCursorPosition(CursorLeft, CursorTop);

                switch (counter)
                {
                    case 0: Console.Write("/"); break;
                    case 1: Console.Write("-"); break;
                    case 2: Console.Write("\\"); break;
                    case 3: Console.Write("|"); counter = -1; break;
                }
                Console.SetCursorPosition(OldLeft, OldTop);
            }

            Thread.Sleep(rate);
        }
        lock (console)
        {   // clean up
            int OldLeft = Console.CursorLeft;
            int OldTop = Console.CursorTop;
            Console.SetCursorPosition(CursorLeft, CursorTop);
            Console.Write(' ');
            Console.SetCursorPosition(OldLeft, OldTop);
        }
    }

    public void Dispose()
    {
        Stop();
    }
}

अच्छा संशोधन, हालांकि नमूना कोड मेरा नहीं है। यह ब्रैड अब्राम्स के ब्लॉग से लिया गया है (मेरे उत्तर में लिंक देखें)। मुझे लगता है कि यह सिर्फ एक सरल नमूना के रूप में लिखा गया है जो सेटसर्कसपोजिशन का प्रदर्शन कर रहा है। Btw, मैं निश्चित रूप से आश्चर्यचकित हूं (एक सकारात्मक तरीके से) चर्चा के बारे में जो मैंने सोचा था कि वह सिर्फ एक साधारण नमूना था। यही कारण है कि मैं इस साइट से प्यार करता हूं :-)
डिर्क वोल्मार

4

स्पष्ट रूप से अंत में एक नई लाइन (\ n) का उपयोग करके (संक्षेप में या स्पष्ट रूप से) के बजाय लाइन की शुरुआत में कैरेज रिटर्न (\ r) का उपयोग करना चाहिए जो आपको चाहिए। उदाहरण के लिए:

void demoPercentDone() {
    for(int i = 0; i < 100; i++) {
        System.Console.Write( "\rProcessing {0}%...", i );
        System.Threading.Thread.Sleep( 1000 );
    }
    System.Console.WriteLine();    
}

-1, प्रश्न C # के लिए पूछता है, मैं इसे C # में फिर से
लिखता हूं

यह आपके सी # बैक को एफ # में बदलने के बजाय एक संपादन संघर्ष की तरह दिखता है। आपका यह परिवर्तन आपके बाद एक मिनट था, और स्प्रिंट पर फ़ोकस किया गया था।
एंडी

संपादन के लिए धन्यवाद। मैं चीजों का परीक्षण करने के लिए एफ # इंटरएक्टिव मोड का उपयोग करता हूं और लगा कि महत्वपूर्ण भाग बीसीएल कॉल थे, जो सी # में समान हैं।
जेम्स ह्यूगार्ड

3
    public void Update(string data)
    {
        Console.Write(string.Format("\r{0}", "".PadLeft(Console.CursorLeft, ' ')));
        Console.Write(string.Format("\r{0}", data));
    }

1

MSDN में कंसोल डॉक्स से:

आप इस समस्या को हल या त्रुटि संपत्ति की TextWriter.NewLine गुण को दूसरी पंक्ति समाप्ति स्ट्रिंग पर सेट करके हल कर सकते हैं। उदाहरण के लिए, C # कथन, Console.Error.NewLine = "\ r \ n \ r \ n";; मानक त्रुटि आउटपुट स्ट्रीम के लिए दो गाड़ी वापसी और लाइन फ़ीड अनुक्रम के लिए लाइन समाप्ति स्ट्रिंग सेट करता है। फिर आप स्पष्ट रूप से त्रुटि आउटपुट स्ट्रीम ऑब्जेक्ट के WriteLine विधि को कॉल कर सकते हैं, जैसा कि C # स्टेटमेंट में, Console.Error.WriteLine ();

तो - मैंने ऐसा किया:

Console.Out.Newline = String.Empty;

फिर मैं खुद आउटपुट को नियंत्रित करने में सक्षम हूं;

Console.WriteLine("Starting item 1:");
    Item1();
Console.WriteLine("OK.\nStarting Item2:");

वहां पहुंचने का दूसरा तरीका।


तुम बस Console.Write () एक ही उद्देश्य के लिए उपयोग कर सकते हैं, NewLine संपत्ति को फिर से परिभाषित किए बिना ...
Radosław Gers

1

यह काम करता है यदि आप बनाना चाहते हैं फ़ाइलों को शांत देखो।

                int num = 1;
                var spin = new ConsoleSpinner();
                Console.ForegroundColor = ConsoleColor.Green;
                Console.Write("");
                while (true)
                {
                    spin.Turn();
                    Console.Write("\r{0} Generating Files ", num);
                    num++;
                }

और यह वह विधि है जो मैंने नीचे कुछ उत्तर से प्राप्त की और इसे संशोधित किया

public class ConsoleSpinner
    {
        int counter;

        public void Turn()
        {
            counter++;
            switch (counter % 4)
            {
                case 0: Console.Write("."); counter = 0; break;
                case 1: Console.Write(".."); break;
                case 2: Console.Write("..."); break;
                case 3: Console.Write("...."); break;
                case 4: Console.Write("\r"); break;
            }
            Thread.Sleep(100);
            Console.SetCursorPosition(23, Console.CursorTop);
        }
    }

0

यहाँ एक और एक है: डी

class Program
{
    static void Main(string[] args)
    {
        Console.Write("Working... ");
        int spinIndex = 0;
        while (true)
        {
            // obfuscate FTW! Let's hope overflow is disabled or testers are impatient
            Console.Write("\b" + @"/-\|"[(spinIndex++) & 3]);
        }
    }
}

0

यदि आप एक पंक्ति को अद्यतन करना चाहते हैं, लेकिन जानकारी एक पंक्ति में दिखाने के लिए बहुत लंबी है, तो उसे कुछ नई लाइनों की आवश्यकता हो सकती है। मैंने इस समस्या का सामना किया है, और नीचे इसे हल करने का एक तरीका है।

public class DumpOutPutInforInSameLine
{

    //content show in how many lines
    int TotalLine = 0;

    //start cursor line
    int cursorTop = 0;

    // use to set  character number show in one line
    int OneLineCharNum = 75;

    public void DumpInformation(string content)
    {
        OutPutInSameLine(content);
        SetBackSpace();

    }
    static void backspace(int n)
    {
        for (var i = 0; i < n; ++i)
            Console.Write("\b \b");
    }

    public  void SetBackSpace()
    {

        if (TotalLine == 0)
        {
            backspace(OneLineCharNum);
        }
        else
        {
            TotalLine--;
            while (TotalLine >= 0)
            {
                backspace(OneLineCharNum);
                TotalLine--;
                if (TotalLine >= 0)
                {
                    Console.SetCursorPosition(OneLineCharNum, cursorTop + TotalLine);
                }
            }
        }

    }

    private void OutPutInSameLine(string content)
    {
        //Console.WriteLine(TotalNum);

        cursorTop = Console.CursorTop;

        TotalLine = content.Length / OneLineCharNum;

        if (content.Length % OneLineCharNum > 0)
        {
            TotalLine++;

        }

        if (TotalLine == 0)
        {
            Console.Write("{0}", content);

            return;

        }

        int i = 0;
        while (i < TotalLine)
        {
            int cNum = i * OneLineCharNum;
            if (i < TotalLine - 1)
            {
                Console.WriteLine("{0}", content.Substring(cNum, OneLineCharNum));
            }
            else
            {
                Console.Write("{0}", content.Substring(cNum, content.Length - cNum));
            }
            i++;

        }
    }

}
class Program
{
    static void Main(string[] args)
    {

        DumpOutPutInforInSameLine outPutInSameLine = new DumpOutPutInforInSameLine();

        outPutInSameLine.DumpInformation("");
        outPutInSameLine.DumpInformation("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb");


        outPutInSameLine.DumpInformation("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
        outPutInSameLine.DumpInformation("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb");

        //need several lines
        outPutInSameLine.DumpInformation("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
        outPutInSameLine.DumpInformation("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb");

        outPutInSameLine.DumpInformation("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
        outPutInSameLine.DumpInformation("bbbbbbbbbbbbbbbbbbbbbbbbbbb");

    }
}

0

मैं vb.net में इसी समाधान की तलाश कर रहा था और मैंने इसे पाया और यह बहुत अच्छा है।

हालाँकि @JohnOdom ने रिक्त स्थान को संभालने के लिए एक बेहतर तरीका सुझाया है यदि पिछले एक से एक बड़ा हो।

मैं vb.net में एक समारोह बनाता हूं और सोचा कि कोई मदद कर सकता है।

यहाँ मेरा कोड है:

Private Sub sPrintStatus(strTextToPrint As String, Optional boolIsNewLine As Boolean = False)
    REM intLastLength is declared as public variable on global scope like below
    REM intLastLength As Integer
    If boolIsNewLine = True Then
        intLastLength = 0
    End If
    If intLastLength > strTextToPrint.Length Then
        Console.Write(Convert.ToChar(13) & strTextToPrint.PadRight(strTextToPrint.Length + (intLastLength - strTextToPrint.Length), Convert.ToChar(" ")))
    Else
        Console.Write(Convert.ToChar(13) & strTextToPrint)
    End If
    intLastLength = strTextToPrint.Length
End Sub

यहां आप स्थानीय स्थैतिक चर की VB सुविधा का उपयोग कर सकते हैं Static intLastLength As Integer:।
मार्क हर्ड

0

मैं यह देखने के लिए एक खोज कर रहा था कि क्या मैंने जो समाधान लिखा है वह गति के लिए अनुकूलित हो सकता है। जो मैं चाहता था वह एक उलटी गिनती टाइमर था, न कि केवल वर्तमान लाइन को अपडेट करना। यहाँ मैं क्या लेकर आया हूँ। किसी के लिए उपयोगी हो सकता है

            int sleepTime = 5 * 60;    // 5 minutes

            for (int secondsRemaining = sleepTime; secondsRemaining > 0; secondsRemaining --)
            {
                double minutesPrecise = secondsRemaining / 60;
                double minutesRounded = Math.Round(minutesPrecise, 0);
                int seconds = Convert.ToInt32((minutesRounded * 60) - secondsRemaining);
                Console.Write($"\rProcess will resume in {minutesRounded}:{String.Format("{0:D2}", -seconds)} ");
                Thread.Sleep(1000);
            }
            Console.WriteLine("");

0

@ E.Lahu समाधान से प्रेरित, प्रतिशत के साथ एक बार प्रगति का कार्यान्वयन।

public class ConsoleSpinner
{
    private int _counter;

    public void Turn(Color color, int max, string prefix = "Completed", string symbol = "■",int position = 0)
    {
        Console.SetCursorPosition(0, position);
        Console.Write($"{prefix} {ComputeSpinner(_counter, max, symbol)}", color);
        _counter = _counter == max ? 0 : _counter + 1;
    }

    public string ComputeSpinner(int nmb, int max, string symbol)
    {
        var spinner = new StringBuilder();
        if (nmb == 0)
            return "\r ";

        spinner.Append($"[{nmb}%] [");
        for (var i = 0; i < max; i++)
        {
            spinner.Append(i < nmb ? symbol : ".");
        }

        spinner.Append("]");
        return spinner.ToString();
    }
}


public static void Main(string[] args)
    {
        var progressBar= new ConsoleSpinner();
        for (int i = 0; i < 1000; i++)
        {
            progressBar.Turn(Color.Aqua,100);
            Thread.Sleep(1000);
        }
    }

0

यहाँ मेरे sosh's और 0xA3 के उत्तरों के बारे में बताया गया है। यह स्पिनर को अपडेट करते समय उपयोगकर्ता के संदेशों के साथ कंसोल को अपडेट कर सकता है और इसमें एक लम्बा समय संकेतक भी होता है।

public class ConsoleSpiner : IDisposable
{
    private static readonly string INDICATOR = "/-\\|";
    private static readonly string MASK = "\r{0} {1:c} {2}";
    int counter;
    Timer timer;
    string message;

    public ConsoleSpiner() {
        counter = 0;
        timer = new Timer(200);
        timer.Elapsed += TimerTick;
    }

    public void Start() {
        timer.Start();
    }

    public void Stop() {
        timer.Stop();
        counter = 0;
    }

    public string Message {
        get { return message; }
        set { message = value; }
    }

    private void TimerTick(object sender, ElapsedEventArgs e) {
        Turn();
    }

    private void Turn() {
        counter++;
        var elapsed = TimeSpan.FromMilliseconds(counter * 200);
        Console.Write(MASK, INDICATOR[counter % 4], elapsed, this.Message);
    }

    public void Dispose() {
        Stop();
        timer.Elapsed -= TimerTick;
        this.timer.Dispose();
    }
}

उपयोग कुछ इस प्रकार है:

class Program
{
    static void Main(string[] args)
    {
        using (var spinner = new ConsoleSpiner())
        {
            spinner.Start();
            spinner.Message = "About to do some heavy staff :-)"
            DoWork();
            spinner.Message = "Now processing other staff".
            OtherWork();
            spinner.Stop();
        }
        Console.WriteLine("COMPLETED!!!!!\nPress any key to exit.");

    }
}

-1

यह SetCursorPositionविधि बहु-थ्रेडिंग परिदृश्य में काम करती है, जहाँ अन्य दो विधियाँ नहीं हैं

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.