कंसोल एप्लिकेशन में प्रगति बार


84

मैं एक साधारण सी # कंसोल ऐप लिख रहा हूं जो sftp सर्वर पर फाइलें अपलोड करता है। हालाँकि, फ़ाइलों की मात्रा बड़ी है। मैं या तो अपलोड की गई फ़ाइलों का प्रतिशत या केवल अपलोड की जाने वाली फ़ाइलों की कुल संख्या से अपलोड की जाने वाली फ़ाइलों की संख्या प्रदर्शित करना चाहूंगा।

सबसे पहले, मैं सभी फ़ाइलों और फ़ाइलों की कुल संख्या प्राप्त करता हूं।

string[] filePath = Directory.GetFiles(path, "*");
totalCount = filePath.Length;

फिर मैं फ़ाइल के माध्यम से लूप करता हूं और उन्हें एक-एक करके फ़ॉरच लूप में अपलोड करता हूं।

foreach(string file in filePath)
{
    string FileName = Path.GetFileName(file);
    //copy the files
    oSftp.Put(LocalDirectory + "/" + FileName, _ftpDirectory + "/" + FileName);
    //Console.WriteLine("Uploading file..." + FileName);
    drawTextProgressBar(0, totalCount);
}

फ़ॉरेस्ट लूप में मेरे पास एक प्रगति पट्टी है जिसके साथ मेरे पास समस्याएं हैं। यह ठीक से प्रदर्शित नहीं करता है।

private static void drawTextProgressBar(int progress, int total)
{
    //draw empty progress bar
    Console.CursorLeft = 0;
    Console.Write("["); //start
    Console.CursorLeft = 32;
    Console.Write("]"); //end
    Console.CursorLeft = 1;
    float onechunk = 30.0f / total;

    //draw filled part
    int position = 1;
    for (int i = 0; i < onechunk * progress; i++)
    {
        Console.BackgroundColor = ConsoleColor.Gray;
        Console.CursorLeft = position++;
        Console.Write(" ");
    }

    //draw unfilled part
    for (int i = position; i <= 31 ; i++)
    {
        Console.BackgroundColor = ConsoleColor.Green;
        Console.CursorLeft = position++;
        Console.Write(" ");
    }

    //draw totals
    Console.CursorLeft = 35;
    Console.BackgroundColor = ConsoleColor.Black;
    Console.Write(progress.ToString() + " of " + total.ToString() + "    "); //blanks at the end remove any excess
}

उत्पादन 1943 में सिर्फ [] 0 है

मुझसे यहां क्या गलत हो रहा है?

संपादित करें:

मैं XML फ़ाइलों को लोड और निर्यात करते समय प्रगति बार प्रदर्शित करने का प्रयास कर रहा हूं। हालांकि, यह एक लूप से गुजर रहा है। इसके बाद पहला राउंड खत्म होने के बाद यह दूसरे और इतने पर जाता है।

string[] xmlFilePath = Directory.GetFiles(xmlFullpath, "*.xml");
Console.WriteLine("Loading XML files...");
foreach (string file in xmlFilePath)
{
     for (int i = 0; i < xmlFilePath.Length; i++)
     {
          //ExportXml(file, styleSheet);
          drawTextProgressBar(i, xmlCount);
          count++;
     }
 }

यह पाश के लिए कभी नहीं छोड़ता ... कोई सुझाव?


XmlCount और गणना क्या है?
eddie_cat

बस इन्क्रीमेंट गिनो। xmlCount निर्दिष्ट फ़ोल्डर DirectoryInfo xmlDir = new DirectoryInfo (xmlFullpath) में XML फ़ाइलों की कुल संख्या है; xmlCount = xmlDir.GetFiles ()। लंबाई;
smr5

1
इसके अलावा, फॉरच लूप के अंदर लूप के लिए क्यों है? यह एक ही बात पर पुनरावृत्ति करने लगता है। यह संभव नहीं है कि फॉरच लूप को रखा जाए।
eddie_cat

1
क्या आपने बाहरी फॉरेस्ट लूप को हटा दिया था? परिवर्तन की टिप्पणी के लिएExportXml(xmlFilePath[i])
eddie_cat

1
वह यह था। मेरे पास सिर्फ लूप है और यह काम करता है।
smr5

जवाबों:


11

यह रेखा आपकी समस्या है:

drawTextProgressBar(0, totalCount);

आप कह रहे हैं कि प्रगति हर पुनरावृत्ति में शून्य है, इसे बढ़ाया जाना चाहिए। हो सकता है इसके बजाय लूप के लिए उपयोग करें।

for (int i = 0; i < filePath.length; i++)
{
    string FileName = Path.GetFileName(filePath[i]);
    //copy the files
    oSftp.Put(LocalDirectory + "/" + FileName, _ftpDirectory + "/" + FileName);
    //Console.WriteLine("Uploading file..." + FileName);
    drawTextProgressBar(i, totalCount);
}

इसने पहली बार काम किया, और मैं दूसरी जगह एक ही काम कर रहा हूं और यह एक लूप का कारण बन रहा है। यह कभी रुकता नहीं है। मैंने अपनी पोस्ट अपडेट की। क्या आप इस पर एक नज़र डाल सकते हैं? धन्यवाद।
smr5

आपने क्या अपडेट किया? यह मुझे वही दिखता है, जो मुझे याद आ रहा है?
एडी_काट

200

मुझे कंसोल प्रोग्रेस बार की भी तलाश थी। मुझे वह नहीं मिला, जो मुझे चाहिए था, इसलिए मैंने अपना रोल करने का फैसला किया। सोर्स कोड (MIT लाइसेंस) के लिए यहां क्लिक करें

एनिमेटेड प्रगति बार

विशेषताएं:

  • पुनर्निर्देशित आउटपुट के साथ काम करता है

    यदि आप कंसोल एप्लिकेशन (जैसे Program.exe > myfile.txt) के आउटपुट को रीडायरेक्ट करते हैं , तो अधिकांश कार्यान्वयन अपवाद के साथ क्रैश हो जाएंगे। ऐसा इसलिए है क्योंकि Console.CursorLeftऔर Console.SetCursorPosition()रीडायरेक्ट उत्पादन का समर्थन नहीं करते।

  • औजार IProgress<double>

    यह आपको async ऑपरेशंस के साथ प्रगति पट्टी का उपयोग करने की अनुमति देता है जो [0..1] की सीमा में प्रगति की रिपोर्ट करता है।

  • सुरक्षित धागा

  • तेज

    Consoleवर्ग अपनी निराशाजनक प्रदर्शन के लिए कुख्यात है। इसके लिए बहुत सारे कॉल आते हैं, और आपका एप्लिकेशन धीमा हो जाता है। यह वर्ग प्रति सेकंड केवल 8 कॉल करता है, भले ही आप कितनी बार एक प्रगति अपडेट की रिपोर्ट करें।

इसे इस तरह उपयोग करें:

Console.Write("Performing some task... ");
using (var progress = new ProgressBar()) {
    for (int i = 0; i <= 100; i++) {
        progress.Report((double) i / 100);
        Thread.Sleep(20);
    }
}
Console.WriteLine("Done.");

4
यह बहुत साफ दिखता है! क्या आप एमआईटी जैसे ओएसएस लाइसेंस को जोड़ने पर विचार करेंगे? choosealicense.com
डैनियल

2
अच्छा विचार। हो गया।
डैनियल वुल्फ

@DanielWolf आपको कंसोल कैसे मिला। CursorPosition बदलने से?
JJS

1
@knocte: उत्पादन कोड में, मैं निश्चित रूप से होगा। यहाँ लक्ष्य यह था कि उदाहरण को यथासंभव संक्षिप्त रखा जाए और संबंधित भागों से ध्यान न हटाया जाए।
डैनियल वुल्फ

8
जिफ आकर्षक है।
लेई यांग

18

मुझे पता है कि यह एक पुराना धागा है, और स्वयं को बढ़ावा देने के लिए माफी माँगता हूँ, हालाँकि मैंने हाल ही में nuget Goblinfactory पर उपलब्ध एक ओपन सोर्स कंसोल लाइब्रेरी लिखी है। थ्रेडसेफ़ मल्टीपल प्रोग्रेस बार सपोर्ट के साथ कंसोल , जो किसी को भी इस पेज को नया बनाने में मदद कर सकता है। मुख्य धागा ब्लॉक नहीं करता है।

यह ऊपर दिए गए उत्तरों से कुछ अलग है क्योंकि यह आपको समानांतर में डाउनलोड और कार्यों को किक करने और अन्य कार्यों के साथ जारी रखने की अनुमति देता है;

चीयर्स, आशा है कि यह उपयोगी है

var t1 = Task.Run(()=> {
   var p = new ProgressBar("downloading music",10);
   ... do stuff
});

var t2 = Task.Run(()=> {
   var p = new ProgressBar("downloading video",10);
   ... do stuff
});

var t3 = Task.Run(()=> {
   var p = new ProgressBar("starting server",10);
   ... do stuff .. calling p.Refresh(n);
});

Task.WaitAll(new [] { t1,t2,t3 }, 20000);
Console.WriteLine("all done.");

आपको इस प्रकार का आउटपुट देता है

यहां छवि विवरण दर्ज करें

नगेट पैकेज में कंसोल की एक खिड़की वाले खंड पर लिखने के लिए उपयोगिताओं के साथ पूर्ण कतरन और रैपिंग समर्थन, प्लस PrintAtऔर विभिन्न अन्य सहायक कक्षाएं भी शामिल हैं।

मैंने नगेट पैकेज लिखा था क्योंकि मैंने जब भी निर्माण और ऑप्स कंसोल स्क्रिप्ट और उपयोगिताओं को लिखा था तब मैंने बहुत सारे सामान्य कंसोल रूटीन लिखना लगातार समाप्त कर दिया था।

यदि मैं कई फ़ाइलों को डाउनलोड कर रहा था, तो मैं धीरे-धीरे Console.Writeप्रत्येक थ्रेड पर स्क्रीन के लिए उपयोग करता था, और स्क्रीन पर इंटरलेव्ड आउटपुट को पढ़ने में आसान बनाने के लिए विभिन्न ट्रिक आजमाता था, जैसे अलग-अलग रंग या नंबर। मैंने अंततः विंडो लाइब्रेरी लिखी, ताकि विभिन्न थ्रेड्स से आउटपुट को अलग-अलग विंडो में प्रिंट किया जा सके, और इसने मेरी उपयोगिता लिपियों में एक टन बॉयलरप्लेट कोड को काट दिया।

उदाहरण के लिए, यह कोड,

        var con = new Window(200,50);
        con.WriteLine("starting client server demo");
        var client = new Window(1, 4, 20, 20, ConsoleColor.Gray, ConsoleColor.DarkBlue, con);
        var server = new Window(25, 4, 20, 20, con);
        client.WriteLine("CLIENT");
        client.WriteLine("------");
        server.WriteLine("SERVER");
        server.WriteLine("------");
        client.WriteLine("<-- PUT some long text to show wrapping");
        server.WriteLine(ConsoleColor.DarkYellow, "--> PUT some long text to show wrapping");
        server.WriteLine(ConsoleColor.Red, "<-- 404|Not Found|some long text to show wrapping|");
        client.WriteLine(ConsoleColor.Red, "--> 404|Not Found|some long text to show wrapping|");

        con.WriteLine("starting names demo");
        // let's open a window with a box around it by using Window.Open
        var names = Window.Open(50, 4, 40, 10, "names");
        TestData.MakeNames(40).OrderByDescending(n => n).ToList()
             .ForEach(n => names.WriteLine(n));

        con.WriteLine("starting numbers demo");
        var numbers = Window.Open(50, 15, 40, 10, "numbers", 
              LineThickNess.Double,ConsoleColor.White,ConsoleColor.Blue);
        Enumerable.Range(1,200).ToList()
             .ForEach(i => numbers.WriteLine(i.ToString())); // shows scrolling

यह पैदा करता है

यहां छवि विवरण दर्ज करें

आप एक विंडो के अंदर प्रगति विंडो भी लिख सकते हैं जितनी आसानी से खिड़कियों पर लिख सकते हैं। (मिश्रण और मैच)।


यह सिर्फ सबसे अच्छा है
प्रतिक

9

आप https://www.nuget.org/packages/ShellProgressBar/ आज़माना चाह सकते हैं

मैं सिर्फ इस प्रगति बार कार्यान्वयन पर ठोकर खाई - इसका क्रॉस प्लेटफ़ॉर्म, उपयोग करने के लिए वास्तव में आसान, काफी विन्यास योग्य और वह करता है जो इसे सही बॉक्स से बाहर करना चाहिए।

सिर्फ साझा करना क्योंकि मुझे यह बहुत पसंद आया।


6

मैंने आपके ProgressBarतरीके को कॉपी किया है । क्योंकि आपकी त्रुटि लूप में थी क्योंकि स्वीकृत उत्तर का उल्लेख किया गया था। लेकिन ProgressBarविधि में कुछ सिंटैक्स त्रुटियां भी हैं। यहां वर्किंग वर्जन है। ज़रा - सा संशोधित।

private static void ProgressBar(int progress, int tot)
{
    //draw empty progress bar
    Console.CursorLeft = 0;
    Console.Write("["); //start
    Console.CursorLeft = 32;
    Console.Write("]"); //end
    Console.CursorLeft = 1;
    float onechunk = 30.0f / tot;

    //draw filled part
    int position = 1;
    for (int i = 0; i < onechunk * progress; i++)
    {
        Console.BackgroundColor = ConsoleColor.Green;
        Console.CursorLeft = position++;
        Console.Write(" ");
    }

    //draw unfilled part
    for (int i = position; i <= 31; i++)
    {
        Console.BackgroundColor = ConsoleColor.Gray;
        Console.CursorLeft = position++;
        Console.Write(" ");
    }

    //draw totals
    Console.CursorLeft = 35;
    Console.BackgroundColor = ConsoleColor.Black;
    Console.Write(progress.ToString() + " of " + tot.ToString() + "    "); //blanks at the end remove any excess
}

कृपया ध्यान दें कि @ डैनियल-भेड़िया एक बेहतर दृष्टिकोण है: https://stackoverflow.com/a/31193455/169714


6

मैंने यह आसान वर्ग बनाया है जो System.Reactive के साथ काम करता है। मुझे आशा है कि आपको यह काफी प्यारा लगेगा।

public class ConsoleDisplayUpdater : IDisposable
{
    private readonly IDisposable progressUpdater;

    public ConsoleDisplayUpdater(IObservable<double> progress)
    {
        progressUpdater = progress.Subscribe(DisplayProgress);
    }

    public int Width { get; set; } = 50;

    private void DisplayProgress(double progress)
    {
        if (double.IsNaN(progress))
        {
            return;
        }

        var progressBarLenght = progress * Width;
        System.Console.CursorLeft = 0;
        System.Console.Write("[");
        var bar = new string(Enumerable.Range(1, (int) progressBarLenght).Select(_ => '=').ToArray());

        System.Console.Write(bar);

        var label = $@"{progress:P0}";
        System.Console.CursorLeft = (Width -label.Length) / 2;
        System.Console.Write(label);
        System.Console.CursorLeft = Width;
        System.Console.Write("]");
    }

    public void Dispose()
    {
        progressUpdater?.Dispose();
    }
}

5

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

drawTextProgressBar(4114, 4114)

मैंने अनावश्यक लूपिंग को हटाने के लिए ड्राइंग कोड में से कुछ किया, जिसने उपरोक्त समस्या को ठीक कर दिया और चीजों को भी थोड़ा-थोड़ा कर दिया:

public static void drawTextProgressBar(string stepDescription, int progress, int total)
{
    int totalChunks = 30;

    //draw empty progress bar
    Console.CursorLeft = 0;
    Console.Write("["); //start
    Console.CursorLeft = totalChunks + 1;
    Console.Write("]"); //end
    Console.CursorLeft = 1;

    double pctComplete = Convert.ToDouble(progress) / total;
    int numChunksComplete = Convert.ToInt16(totalChunks * pctComplete);

    //draw completed chunks
    Console.BackgroundColor = ConsoleColor.Green;
    Console.Write("".PadRight(numChunksComplete));

    //draw incomplete chunks
    Console.BackgroundColor = ConsoleColor.Gray;
    Console.Write("".PadRight(totalChunks - numChunksComplete));

    //draw totals
    Console.CursorLeft = totalChunks + 5;
    Console.BackgroundColor = ConsoleColor.Black;

    string output = progress.ToString() + " of " + total.ToString();
    Console.Write(output.PadRight(15) + stepDescription); //pad the output so when changing from 3 to 4 digits we avoid text shifting
}

यह सामान्य रूप से काम करता है सिवाय इसके कि यह पहले के किसी भी पाठ की तरह पिछले कंसोल आउटपुट को हटाता है और इसके बाद यह एक नई पंक्ति में नहीं जाता है ....
डेविड श्नैडर

0

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

public static bool DownloadFile(List<string> files, string host, string username, string password, string savePath)
    {
        try
        {
            //setup FTP client

            foreach (string f in files)
            {
                FILENAME = f.Split('\\').Last();
                wc.DownloadFileCompleted += new AsyncCompletedEventHandler(Completed);
                wc.DownloadProgressChanged += new DownloadProgressChangedEventHandler(ProgressChanged);
                wc.DownloadFileAsync(new Uri(host + f), savePath + f);
                while (wc.IsBusy)
                    System.Threading.Thread.Sleep(1000);
                Console.Write("  COMPLETED!");
                Console.WriteLine();
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.ToString());
            return false;
        }
        return true;
    }

    private static void ProgressChanged(object obj, System.Net.DownloadProgressChangedEventArgs e)
    {
        Console.Write("\r --> Downloading " + FILENAME +": " + string.Format("{0:n0}", e.BytesReceived / 1000) + " kb");
    }

    private static void Completed(object obj, AsyncCompletedEventArgs e)
    {
    }

यहाँ आउटपुट का एक उदाहरण है: यहां छवि विवरण दर्ज करें

आशा है कि यह किसी की मदद करता है!


2
@regisbsb वे प्रगति पट्टियाँ नहीं हैं, ऐसा लगता है कि उन्होंने फ़ाइल नामों का सेंसर भाग दिया :) मुझे पता है, मुझे पहले भी खुद को बेवकूफ बनाया गया था।
रेशमकीट

-1

मैं अभी भी थोड़ा नया C#हूं लेकिन मेरा मानना ​​है कि नीचे मदद कर सकता है।

string[] xmlFilePath = Directory.GetFiles(xmlFullpath, "*.xml");
Console.WriteLine("Loading XML files...");
int count = 0;
foreach (string file in xmlFilePath)
{
    //ExportXml(file, styleSheet);
    drawTextProgressBar(count, xmlCount);
    count++;
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.