sftp 서버에 파일을 업로드하는 간단한 C # 콘솔 앱을 작성 중입니다. 그러나 파일의 양이 많습니다. 업로드 할 총 파일 수에서 업로드 된 파일의 비율 또는 이미 업로드 된 파일 수를 표시하고 싶습니다.
먼저 모든 파일과 총 파일 수를 얻습니다.
string[] filePath = Directory.GetFiles(path, "*");
totalCount = filePath.Length;
그런 다음 파일을 반복하고 foreach 루프에서 하나씩 업로드합니다.
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);
}
foreach 루프에는 문제가있는 진행률 표시 줄이 있습니다. 제대로 표시되지 않습니다.
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++;
}
}
for 루프를 떠나지 않습니다 … 제안 사항이 있습니까?
답변
이 줄이 문제입니다.
drawTextProgressBar(0, totalCount);
당신은 모든 반복에서 진행률이 0이라고 말하고 있습니다. 이것은 증가되어야합니다. 대신 for 루프를 사용할 수 있습니다.
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);
}
답변
콘솔 진행률 표시 줄도 찾고있었습니다. 나는 내가 필요로하는 일을하는 것을 찾지 못해서 나만의 것을 결정하기로 결정했습니다. 소스 코드 (MIT 라이선스) 를 보려면 여기를 클릭하십시오 .
풍모:
-
리디렉션 된 출력과 함께 작동
콘솔 애플리케이션 (예 :)의 출력을 리디렉션하면
Program.exe > myfile.txt
대부분의 구현이 예외와 함께 충돌합니다. 그의는 때문에Console.CursorLeft
및Console.SetCursorPosition()
리디렉션 된 출력을 지원하지 않습니다. -
구현
IProgress<double>
이렇게하면 [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.");
답변
나는 이것이 오래된 스레드라는 것을 알고 있으며 자체 프로모션에 대해 사과하지만 최근에 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.");
이러한 유형의 출력을 제공합니다.
Nuget 패키지에는 전체 클리핑 및 래핑 지원과 함께 PrintAt
다양한 기타 유용한 클래스와 함께 콘솔의 창 섹션에 쓰기위한 유틸리티도 포함되어 있습니다 .
빌드 및 운영 콘솔 스크립트와 유틸리티를 작성할 때마다 공통 콘솔 루틴을 많이 작성했기 때문에 nuget 패키지를 작성했습니다.
여러 파일을 다운로드하는 경우 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
이것을 생산
창에 쓰는 것처럼 쉽게 창 안에 진행률 표시 줄을 만들 수도 있습니다. (믹스 앤 매치).
답변
https://www.nuget.org/packages/ShellProgressBar/ 시도해 볼 수 있습니다.
저는이 진행률 표시 줄 구현을 우연히 발견했습니다. 크로스 플랫폼은 정말 사용하기 쉽고 구성이 가능하며 바로 사용할 수있는 작업을 수행합니다.
내가 많이 좋아해서 그냥 공유.
답변
귀하의 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
}
@ Daniel-wolf에는 https://stackoverflow.com/a/31193455/169714 가 더 나은 접근 방식이 있습니다.
답변
원래 포스터의 진행률 표시 줄이 마음에 들었지만 특정 진행률 / 전체 항목 조합에서 진행률이 올바르게 표시되지 않는 것을 발견했습니다. 예를 들어 다음은 올바르게 그려지지 않아 진행률 표시 줄 끝에 추가 회색 블록이 남습니다.
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
}
답변
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();
}
}