Rust 中使用 tokio 異步操作 IO
請注意,異步操作標準 IO 請在 Tokio 的運行時上下文中使用,它們需要 Tokio 的一些特性。否則會發生 panic。
tokio 適合 IO 等待比較多的場景,不適合 CPU 密集型場景,不適合讀取大量的文件。它比較適合在網絡應用。
標準的輸入輸出簡單使用
use tokio::io::{self, AsyncReadExt, AsyncWriteExt};
#[tokio::main]
async fn main() -> io::Result<()> {
let mut stdout = io::stdout();
stdout
.write_all("請輸入您的暱稱,退出請輸入q\n".as_bytes())
.await?;
let mut stdin = io::stdin();
loop {
let mut buf = vec![0; 1024];
let n = match stdin.read(&mut buf).await {
Err(_) | Ok(0) => break,
Ok(n) => n,
};
buf.truncate(n);
let content = String::from_utf8_lossy(&buf).into_owned();
let content = content.trim_end_matches("\r\n");
if content == "q" {
break;
}
println!("the input is {:?}", content);
}
Ok(())
}
標準 IO 和文件結合起來,演示讀文件內容
use tokio::{
fs::File,
io::{self, AsyncBufReadExt, AsyncReadExt, AsyncWriteExt, BufReader},
};
#[tokio::main]
async fn main() -> io::Result<()> {
let mut stdout = io::stdout();
// 小提示:字符串中包含\n,在窗口中直接顯示文本,不包含,需要按回車才顯示。
stdout
.write_all("打印文件內容,請輸入文件名稱,退出請輸入q\n".as_bytes())
.await?;
let mut stdin = io::stdin();
loop {
let mut buf = vec![0; 1024];
let n = match stdin.read(&mut buf).await {
Err(_) | Ok(0) => break,
Ok(n) => n,
};
buf.truncate(n);
let content = String::from_utf8_lossy(&buf).into_owned();
let content = content.trim_end_matches("\r\n");
if content == "q" {
break;
}
println!("the input is {:?}", content);
let f = File::open(content).await?;
let mut reader = BufReader::new(f);
let mut buffer = String::new();
reader.read_to_string(&mut buffer).await?;
println!("The content: {:?}", buffer);
}
Ok(())
}
從標準輸入中讀取內容,然後寫入到文件中
use tokio::{
fs::File,
io::{self, AsyncReadExt, AsyncWriteExt, BufWriter},
};
#[tokio::main]
async fn main() -> io::Result<()> {
let mut stdout = io::stdout();
// 小提示:字符串中包含\n,在窗口中直接顯示文本,不包含,需要按回車才顯示。
stdout
.write_all("請輸入將要創建文件名稱,退出請輸入q\n".as_bytes())
.await?;
let mut filename = String::new();
let mut stdin = io::stdin();
loop {
let mut buf = vec![0; 1024];
let n = match stdin.read(&mut buf).await {
Err(_) | Ok(0) => break,
Ok(n) => n,
};
buf.truncate(n);
let content = String::from_utf8_lossy(&buf).into_owned();
let content = content.trim_end_matches("\r\n");
if content == "q" {
break;
}
if content.len() > 0 {
filename = content.to_owned();
break;
}
}
let f = File::create(filename.as_str()).await?;
let mut writer = BufWriter::new(f);
stdout
.write_all("請輸入你要寫入的內容,退出請輸入q\n".as_bytes())
.await?;
loop {
let mut buf = vec![0; 1024];
let n = match stdin.read(&mut buf).await {
Err(_) | Ok(0) => break,
Ok(n) => n,
};
buf.truncate(n);
let content = String::from_utf8_lossy(&buf).into_owned();
let content = content.trim_end_matches("\r\n");
if content == "q" {
break;
}
println!("the input is {:?}", content);
writer.write(content.as_bytes()).await?;
writer.write(b"\n").await?;
}
writer.flush().await?;
Ok(())
}
它提供一些有用的方法:
read_to_end,讀取流中的所有字節,直到碰到 EOF。
write,將緩衝區中的數據寫入到流中,返回寫入的字節數。
write_all,將整個緩衝區中的數據都寫入到流中。
copy,從流中讀取的內容再寫入到流中。使用這個函數可以方便的實現回聲功能。
理解之後,會感覺設計的非常妙。
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/8XvIyByXqkYz2WlPU0XMqA