Ist es beim Erstellen einer Windows-Konsolen-App in C # möglich, in die Konsole zu schreiben, ohne eine aktuelle Zeile erweitern oder in eine neue Zeile wechseln zu müssen? Wenn ich beispielsweise einen Prozentsatz anzeigen möchte, der angibt, wie kurz ein Prozess vor dem Abschluss steht, möchte ich nur den Wert in derselben Zeile wie den Cursor aktualisieren und muss nicht jeden Prozentsatz in eine neue Zeile setzen.
Kann dies mit einer "Standard" C # -Konsolen-App durchgeführt werden?
Antworten:
Wenn Sie nur
"\r"
auf der Konsole drucken , kehrt der Cursor zum Anfang der aktuellen Zeile zurück und Sie können ihn neu schreiben. Dies sollte den Trick tun:Beachten Sie die wenigen Leerzeichen nach der Nummer, um sicherzustellen, dass alles, was zuvor vorhanden war, gelöscht wird.
Beachten Sie auch die Verwendung von
Write()
anstelle von,WriteLine()
da Sie am Ende der Zeile kein "\ n" hinzufügen möchten.quelle
PadRight
natürlich zuerst die ungepolsterte Zeichenfolge oder Länge speichern).Mit können Sie
Console.SetCursorPosition
die Position des Cursors einstellen und dann an der aktuellen Position schreiben.Hier ist ein Beispiel, das einen einfachen "Spinner" zeigt:
Beachten Sie, dass Sie sicherstellen müssen, dass vorhandene Ausgaben mit neuen Ausgaben oder Leerzeichen überschrieben werden.
Update: Da kritisiert wurde, dass das Beispiel den Cursor nur um ein Zeichen zurückbewegt, füge ich dies zur Verdeutlichung hinzu: Mit können
SetCursorPosition
Sie den Cursor auf eine beliebige Position im Konsolenfenster setzen.setzt den Cursor auf den Anfang der aktuellen Zeile (oder Sie können ihn
Console.CursorLeft = 0
direkt verwenden).quelle
SetCursorPosition
(oderCursorLeft
) können Sie flexibler arbeiten, z. B. nicht am Zeilenanfang schreiben, im Fenster nach oben gehen usw. Dies ist also ein allgemeinerer Ansatz, der z. B. für die Ausgabe verwendet werden kann Benutzerdefinierte Fortschrittsbalken oder ASCII-Grafik.Bisher haben wir drei konkurrierende Alternativen, um dies zu tun:
Ich habe immer
Console.CursorLeft = 0
eine Variation der dritten Option verwendet, also habe ich beschlossen, einige Tests durchzuführen. Hier ist der Code, den ich verwendet habe:Auf meinem Computer erhalte ich folgende Ergebnisse:
Außerdem
SetCursorPosition
verursachte sich ein merkliches Flackern, das ich bei keiner der Alternativen beobachtete. Die Moral ist es also, wenn möglich Backspaces oder Wagenrückläufe zu verwenden , und danke, dass Sie mir einen schnelleren Weg beigebracht haben, SO!Update : In den Kommentaren schlägt Joel vor, dass SetCursorPosition in Bezug auf die zurückgelegte Strecke konstant ist, während die anderen Methoden linear sind. Weitere Tests bestätigen, dass dies der Fall ist, jedoch ist konstante Zeit und langsam immer noch langsam. In meinen Tests ist das Schreiben einer langen Reihe von Backspaces in die Konsole schneller als bei SetCursorPosition, bis etwa 60 Zeichen erreicht sind. Die Rücktaste ist also schneller, um Teile der Zeile zu ersetzen, die kürzer als 60 Zeichen (oder so) sind, und sie flackert nicht. Daher werde ich zu meiner anfänglichen Bestätigung von \ b über \ r und stehen
SetCursorPosition
.quelle
Sie können die Escape-Sequenz \ b (Rücktaste) verwenden, um eine bestimmte Anzahl von Zeichen in der aktuellen Zeile zu sichern. Dadurch wird nur der aktuelle Speicherort verschoben und die Zeichen werden nicht entfernt.
Zum Beispiel:
Hier ist Zeile die prozentuale Zeile, die in die Konsole geschrieben werden soll. Der Trick besteht darin, die richtige Anzahl von \ b Zeichen für die vorherige Ausgabe zu generieren .
Der Vorteil gegenüber dem \ r- Ansatz besteht darin, dass if funktioniert, auch wenn sich Ihre prozentuale Ausgabe nicht am Zeilenanfang befindet.
quelle
\r
wird für diese Szenarien verwendet.\r
stellt einen Wagenrücklauf dar, was bedeutet, dass der Cursor zum Zeilenanfang zurückkehrt.Aus diesem Grund verwendet Windows
\n\r
als neue Linienmarkierung.\n
Bewegt Sie eine Zeile nach unten und\r
bringt Sie zum Anfang der Zeile zurück.quelle
Ich musste nur mit der
ConsoleSpinner
Klasse des Divos spielen . Meins ist bei weitem nicht so prägnant, aber es hat mir einfach nicht gut gefallen, dass Benutzer dieser Klasse ihre eigenewhile(true)
Schleife schreiben müssen . Ich fotografiere für eine Erfahrung wie diese:Und ich habe es mit dem folgenden Code realisiert. Da ich nicht möchte, dass meine
Start()
Methode blockiert, möchte ich nicht, dass sich der Benutzer um das Schreiben einerwhile(spinFlag)
ähnlichen Schleife kümmern muss , und ich möchte mehreren Spinnern gleichzeitig erlauben, dass ich einen separaten Thread erzeugen muss, um das zu handhaben Spinnen. Und das bedeutet, dass der Code viel komplizierter sein muss.Außerdem habe ich nicht so viel Multithreading durchgeführt, so dass es möglich ist (wahrscheinlich sogar), dass ich ein oder drei subtile Fehler hinterlassen habe. Aber es scheint bisher ziemlich gut zu funktionieren:
quelle
Die explizite Verwendung eines Carrage Return (\ r) am Anfang der Zeile anstelle (implizit oder explizit) der Verwendung einer neuen Zeile (\ n) am Ende sollte das gewünschte Ergebnis erzielen. Zum Beispiel:
quelle
quelle
Aus den Konsolendokumenten in MSDN:
Also - ich habe das gemacht:
Dann kann ich die Ausgabe selbst steuern;
Ein anderer Weg dorthin.
quelle
Dies funktioniert, wenn Sie das Generieren von Dateien cool aussehen lassen möchten.
Und dies ist die Methode, die ich aus einer Antwort unten erhalten und modifiziert habe
quelle
Hier ist noch einer: D.
quelle
Wenn Sie eine Zeile aktualisieren möchten, die Informationen jedoch zu lang sind, um in einer Zeile angezeigt zu werden, sind möglicherweise einige neue Zeilen erforderlich. Ich bin auf dieses Problem gestoßen, und im Folgenden finden Sie eine Möglichkeit, dies zu lösen.
quelle
Ich habe nach der gleichen Lösung in vb.net gesucht und diese gefunden und sie ist großartig.
Da @JohnOdom jedoch eine bessere Möglichkeit vorgeschlagen hat, mit dem Leerzeichen umzugehen, wenn das vorherige größer als das aktuelle ist.
Ich mache eine Funktion in vb.net und dachte, jemand könnte geholfen werden ..
Hier ist mein Code:
quelle
Static intLastLength As Integer
.Ich habe danach gesucht, um zu sehen, ob die von mir geschriebene Lösung auf Geschwindigkeit optimiert werden kann. Was ich wollte, war ein Countdown-Timer, der nicht nur die aktuelle Zeile aktualisiert. Folgendes habe ich mir ausgedacht. Könnte für jemanden nützlich sein
quelle
Inspiriert von @ E.Lahu Solution, Implementierung eines Balkenfortschritts mit Prozentsatz.
quelle
Hier ist meine Sicht auf die Antworten von s soosh und 0xA3. Es kann die Konsole mit Benutzermeldungen aktualisieren, während der Spinner aktualisiert wird, und verfügt auch über eine Anzeige für die verstrichene Zeit.
Nutzung ist so etwas wie:
quelle
Die
SetCursorPosition
Methode funktioniert in einem Multithreading-Szenario, in dem die beiden anderen Methoden dies nicht tunquelle