如何覆盖控制台输出?

Jon*_*ght 7 console rust

有没有办法使用 Rust 而不是简单地附加来覆盖控制台输出?

一个例子是打印进度的百分比;我宁愿覆盖该行也不愿打印新行。

Mic*_*son 7

控制台通常通过打印“控制字符”来控制,但它们是什么取决于平台和终端类型。您可能不想重新发明轮子来做到这一点。

您可以使用crossterm crate来获得这种控制台控制。一个简单的例子是:

use std::{thread, time};
use std::io::{Write, stdout};
use crossterm::{QueueableCommand, cursor};

fn main() {
    let mut stdout = stdout();

    for i in 1..10 {
        stdout.queue(cursor::SavePosition);
        stdout.write(format!("Here!!! {}", i).as_bytes());
        stdout.queue(cursor::RestorePosition);
        stdout.flush();
        thread::sleep(time::Duration::from_millis(500));
    }

    println!("Hello, world!");
}
Run Code Online (Sandbox Code Playgroud)


小智 7

对于较低级别的方法,您可以使用\r转义将光标返回到行的开头并从那里覆盖。

use std::{
    io::{stdout, Write},
    thread::sleep,
    time::Duration,
};

fn main() {
    let mut stdout = stdout();

    for i in 0..=100 {
        print!("\rProcessing {}%...", i);
        // or
        // stdout.write(format!("\rProcessing {}%...", i).as_bytes()).unwrap();

        stdout.flush().unwrap();
        sleep(Duration::from_millis(20));
    }
    println!();
}
Run Code Online (Sandbox Code Playgroud)

您还可以使用退格字符将光标向后移动一格。

const BACKSPACE: char = 8u8 as char;

print!("{}\rThis replaces the previous line", BACKSPACE);
Run Code Online (Sandbox Code Playgroud)

笔记:

这最适合像这样的简单递增值。如果你写,Hello, World!那么\rbar你最终会得到baro, World!. 如果您想清除输出,最好的方法是跟踪您写入的字符数并用空格覆盖它们,或者您可以使用可以为您提供终端大小的库。