C# 如何修改前一行控制台文本?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10804233/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to modify the previous line of console text?
提问by Harry
I'd like to achieve something like this:
我想实现这样的目标:
Time consuming operation...OK
Another time consuming operation...
And another one, but it completed, so...OK
I displayed 3 line of text, each one related with a thread which can end sooner or later. But if the second one complete later than the third one, I'll get something like this:
我显示了 3 行文本,每一行都与一个迟早会结束的线程相关。但是如果第二个比第三个晚完成,我会得到这样的东西:
Time consuming operation...OK
Another time consuming operation...
And another one, but it completed, so...OKOK
Which is of course unacceptable. I know how to go back in current line, but is there a way to go UP? I'd swear I've seen it somewhere, though it could be a Linux console :)
这当然是不可接受的。我知道如何回到当前行,但是有没有办法向上走?我发誓我在某处见过它,虽然它可能是一个 Linux 控制台:)
Forget it. See Far File Manager! It works in Windows console, it works even in PowerShell! How to make something like this? And the coolest part is it restores console state after exiting. So maybe I should ask - how to access console buffer directly? I assume I'll need some native code to do the trick, but maybe there's another way? I thought of clearing console with each update, but this seems like overkill. Or maybe it isn't? Will it blink?
算了吧。请参阅远程文件管理器!它适用于 Windows 控制台,甚至适用于 PowerShell!如何制作这样的东西?最酷的部分是退出后恢复控制台状态。所以也许我应该问 - 如何直接访问控制台缓冲区?我想我需要一些本机代码来完成这个技巧,但也许还有另一种方法?我想在每次更新时清除控制台,但这似乎有点矫枉过正。或者也许不是?会眨眼吗?
采纳答案by Alexei Levenkov
You can move cursor wherever you want: Console.SetCursorPositionor use Console.CursorTop.
您可以将光标移动到任何您想要的位置:Console.SetCursorPosition或使用Console.CursorTop。
Console.SetCursorPosition(0, Console.CursorTop -1);
Console.WriteLine("Over previous line!!!");
回答by agent-j
Use a carriage return. This sample prints a single line, overwriting what was there before.
使用回车。此示例打印一行,覆盖之前的内容。
Console.WriteLine();
for (int i = 0; i <= 100; i++)
{
System.Threading.Thread.Sleep(10);
Console.Write("\x000DProgress: " + i);
}
This works as long as all your strings are less than 80 columns(or whatever your terminal buffer is set to).
只要您的所有字符串都少于 80 列(或您的终端缓冲区设置为任何值),这就会起作用。
回答by user247702
Note: the following answer was originally edited into the question by the OP.
注意:以下答案最初由 OP 编辑到问题中。
Here's complete solution with demo:
这是带有演示的完整解决方案:
using System;
using System.Collections.Generic;
using System.Threading;
namespace PowerConsole {
internal class Containers {
internal struct Container {
public int Id;
public int X;
public int Y;
public string Content;
}
public static List<Container> Items = new List<Container>();
private static int Identity = 0;
public static int Add(string text) {
var c = new Container();
c.Id = Identity++;
c.X = Console.CursorLeft;
c.Y = Console.CursorTop;
c.Content = text;
Console.Write(text);
Items.Add(c);
return c.Id;
}
public static void Remove(int id) {
Items.RemoveAt(id);
}
public static void Replace(int id, string text) {
int x = Console.CursorLeft, y = Console.CursorTop;
Container c = Items[id];
Console.MoveBufferArea(
c.X + c.Content.Length, c.Y,
Console.BufferWidth - c.X - text.Length, 1,
c.X + text.Length, c.Y
);
Console.CursorLeft = c.X;
Console.CursorTop = c.Y;
Console.Write(text);
c.Content = text;
Console.CursorLeft = x;
Console.CursorTop = y;
}
public static void Clear() {
Items.Clear();
Identity = 0;
}
}
internal class Program {
private static List<Thread> Threads = new List<Thread>();
private static void Main(string[] args) {
Console.WriteLine("So we have some threads:\r\n");
int i, id;
Random r = new Random();
for (i = 0; i < 10; i++) {
Console.Write("Starting thread " + i + "...[");
id = Containers.Add("?");
Console.WriteLine("]");
Thread t = new Thread((object data) => {
Thread.Sleep(r.Next(5000) + 100);
Console.ForegroundColor = ConsoleColor.Green;
Containers.Replace((int)data, "DONE");
Console.ResetColor();
});
Threads.Add(t);
}
Console.WriteLine("\n\"But will it blend?\"...");
Console.ReadKey(true);
i = 0;
Threads.ForEach(t => t.Start(i++));
Threads.ForEach(t => t.Join());
Console.WriteLine("\r\nVoila.");
Console.ReadKey(true);
}
}
}

