亚欧色一区w666天堂,色情一区二区三区免费看,少妇特黄A片一区二区三区,亚洲人成网站999久久久综合,国产av熟女一区二区三区

  • 發布文章
  • 消息中心
點贊
收藏
評論
分享
原創

Tokio 緩存異步 IO 學習文檔

2024-10-28 09:27:15
55
0

一、為什么使用帶緩沖的讀寫?

在 Rust 的異步編程中,AsyncReadExtAsyncWriteExt 提供了方便的讀寫方法。然而,每次調用這些方法,都會向操作系統發起系統調用。如果處理大量數據時,每次只讀或寫少量字節,就會頻繁地切換上下文,造成 ?CPU 時間浪費?,降低 IO 效率。

緩沖讀寫的好處

  1. ?減少系統調用次數?:數據會先寫入緩沖區,當緩沖滿了或條件滿足時才向操作系統發起系統調用。
  2. ?按行讀取?:緩沖讀操作可以識別換行符并按行讀取數據,這比按字節讀取更方便。
  3. ?高效的數據處理?:減少 CPU 資源浪費,提高 IO 性能。

二、使用 BufReaderBufWriter 實現緩沖讀寫

tokio::io 模塊提供了 BufReader 和 ?BufWriter,用于為 Reader 和 Writer 添加緩沖功能。

BufReader 讀取文件按行打印

use tokio::{fs::File, io::{AsyncBufReadExt, BufReader}, runtime};
?
fn main() {
    let rt = runtime::Runtime::new().unwrap();
    rt.block_on(async {
        let f = File::open("a.log").await.unwrap();
        let mut lines = BufReader::new(f).lines();
?
        while let Some(line) = lines.next_line().await.unwrap() {
            println!("read line: {}", line);
        }
    });
}

?解釋?:

  • BufReader 讀取文件時,會將內容緩存在內部緩沖區中。
  • ?按行讀取?:lines() 方法將內容按行分割,next_line() 異步獲取下一行。

BufWriter 寫文件

use tokio::{fs::File, io::{AsyncWriteExt, BufWriter}, runtime};
?
fn main() {
    let rt = runtime::Runtime::new().unwrap();
    rt.block_on(async {
        let f = File::create("output.txt").await.unwrap();
        let mut writer = BufWriter::new(f);
?
        writer.write_all(b"Hello, world!\n").await.unwrap();
        writer.flush().await.unwrap();  // 確保緩沖區數據寫入文件
    });
}

?解釋?:

  • BufWriter 將數據寫入緩沖區,當緩沖區滿或調用 flush() 時,才會將數據寫入文件。
  • ?**write_all()**?:寫入字節數據。

三、按自定義分隔符讀取數據:split()

split() 可以將讀取的內容按指定的字節分隔符分割成多個片段。

示例:按換行符分割文件

use tokio::{fs::File, io::{AsyncBufReadExt, BufReader}, runtime};
?
fn main() {
    let rt = runtime::Runtime::new().unwrap();
    rt.block_on(async {
        let f = File::open("a.log").await.unwrap();
        let mut segments = BufReader::new(f).split(b'\n');
?
        while let Some(segment) = segments.next_segment().await.unwrap() {
            println!("segment: {}", String::from_utf8(segment).unwrap());
        }
    });
}

?解釋?:

  • ?**split(b'\n')**?:按換行符分割文件內容。
  • **每次調用 **next_segment() 獲取一個片段,返回 Vec<u8>

四、隨機讀寫文件:Seek

tokio::io::AsyncSeekExt 提供了 隨機讀寫 功能,可以設置文件的偏移位置,實現非順序的讀寫。

示例:設置偏移位置讀取文件

use std::io::SeekFrom;
use tokio::{fs::File, io::{AsyncReadExt, AsyncSeekExt}, runtime};
?
fn main() {
    let rt = runtime::Runtime::new().unwrap();
    rt.block_on(async {
        let mut f = File::open("a.log").await.unwrap();
?
        f.seek(SeekFrom::Start(5)).await.unwrap();  // 從第5個字節開始讀取
        let mut content = String::new();
        f.read_to_string(&mut content).await.unwrap();
        println!("Data: {}", content);
?
        f.rewind().await.unwrap();  // 將偏移指針重置到文件開頭
    });
}

?解釋?:

  • ?**seek()**?:將偏移指針移動到指定位置。
  • ?**rewind()**?:重置偏移指針到文件開頭。

五、標準輸入輸出

tokio::io 提供了 stdin() 和 ?**stdout()**?,用于異步讀取標準輸入和輸出。

示例:讀取用戶輸入并回顯

use tokio::{io::{AsyncReadExt, AsyncWriteExt}, runtime};
?
fn main() {
    let rt = runtime::Runtime::new().unwrap();
    rt.block_on(async {
        let mut stdin = tokio::io::stdin();
        let mut stdout = tokio::io::stdout();
?
        let mut buffer = vec![0; 1024];
        loop {
            stdout.write(b"Enter something: ").await.unwrap();
            stdout.flush().await.unwrap();
?
            let n = stdin.read(&mut buffer).await.unwrap();
            if n == 0 {
                break;  // 用戶輸入結束
            }
?
            stdout.write(&buffer[..n]).await.unwrap();
            stdout.flush().await.unwrap();
        }
    });
}

?解釋?:

  • ?讀取用戶輸入?:stdin.read() 從標準輸入讀取數據。
  • ?輸出到終端?:stdout.write() 將數據回顯。

六、全雙工通信:DuplexStream

tokio::io::duplex() 提供了類似套接字的全雙工管道,支持讀寫同時進行。

示例:模擬客戶端和服務端的通信

use tokio::{io::{self, AsyncReadExt, AsyncWriteExt}, runtime, time};
?
#[tokio::main]
async fn main() {
    let (mut client, mut server) = io::duplex(64);  // 創建雙向管道
?
    // 啟動一個任務:服務端發送消息
    tokio::spawn(async move {
        server.write_all(b"Hello from server").await.unwrap();
    });
?
    // 客戶端讀取來自服務端的消息
    let mut buf = vec![0; 64];
    let n = client.read(&mut buf).await.unwrap();
    println!("Client received: {}", String::from_utf8_lossy(&buf[..n]));
}

?解釋?:

  • ?**duplex()**?:創建全雙工讀寫管道。
  • ?客戶端和服務端通信?:服務端寫入數據,客戶端讀取數據。

七、拆分 Reader 和 Writer:split()

split() 方法可以將一個可讀寫的目標(如 TcpStream)拆分為 讀半部分 和 ?寫半部分?。

示例:拆分 DuplexStream

use tokio::{io::{self, AsyncReadExt, AsyncWriteExt}, runtime};
?
#[tokio::main]
async fn main() {
    let (client, server) = io::duplex(64);
?
    let (mut reader, writer) = io::split(client);  // 拆分為讀和寫部分
?
    // 關閉不使用的寫部分
    drop(writer);
?
    let mut buf = vec![0; 64];
    let n = reader.read(&mut buf).await.unwrap();
    println!("Read from server: {}", String::from_utf8_lossy(&buf[..n]));
}

八、總結

**在這一部分,教程介紹了如何使用 **Tokio 實現異步 IO,包括:

  1. ?**BufReaderBufWriter**?:用于高效的緩沖讀寫。
  2. ?w按行讀取和自定義分隔符?:方便處理文本數據。
  3. ?隨機讀寫文件?:通過設置偏移指針實現非順序讀寫。
  4. ?標準輸入輸出?:異步處理用戶輸入和終端輸出。
  5. ?全雙工通信?:通過 DuplexStream 實現雙向數據傳輸。
  6. ?拆分 Reader 和 Writer?:提高代碼的靈活性。w
0條評論
0 / 1000
l****n
17文章數
0粉絲數
l****n
17 文章 | 0 粉絲
原創

Tokio 緩存異步 IO 學習文檔

2024-10-28 09:27:15
55
0

一、為什么使用帶緩沖的讀寫?

在 Rust 的異步編程中,AsyncReadExtAsyncWriteExt 提供了方便的讀寫方法。然而,每次調用這些方法,都會向操作系統發起系統調用。如果處理大量數據時,每次只讀或寫少量字節,就會頻繁地切換上下文,造成 ?CPU 時間浪費?,降低 IO 效率。

緩沖讀寫的好處

  1. ?減少系統調用次數?:數據會先寫入緩沖區,當緩沖滿了或條件滿足時才向操作系統發起系統調用。
  2. ?按行讀取?:緩沖讀操作可以識別換行符并按行讀取數據,這比按字節讀取更方便。
  3. ?高效的數據處理?:減少 CPU 資源浪費,提高 IO 性能。

二、使用 BufReaderBufWriter 實現緩沖讀寫

tokio::io 模塊提供了 BufReader 和 ?BufWriter,用于為 Reader 和 Writer 添加緩沖功能。

BufReader 讀取文件按行打印

use tokio::{fs::File, io::{AsyncBufReadExt, BufReader}, runtime};
?
fn main() {
    let rt = runtime::Runtime::new().unwrap();
    rt.block_on(async {
        let f = File::open("a.log").await.unwrap();
        let mut lines = BufReader::new(f).lines();
?
        while let Some(line) = lines.next_line().await.unwrap() {
            println!("read line: {}", line);
        }
    });
}

?解釋?:

  • BufReader 讀取文件時,會將內容緩存在內部緩沖區中。
  • ?按行讀取?:lines() 方法將內容按行分割,next_line() 異步獲取下一行。

BufWriter 寫文件

use tokio::{fs::File, io::{AsyncWriteExt, BufWriter}, runtime};
?
fn main() {
    let rt = runtime::Runtime::new().unwrap();
    rt.block_on(async {
        let f = File::create("output.txt").await.unwrap();
        let mut writer = BufWriter::new(f);
?
        writer.write_all(b"Hello, world!\n").await.unwrap();
        writer.flush().await.unwrap();  // 確保緩沖區數據寫入文件
    });
}

?解釋?:

  • BufWriter 將數據寫入緩沖區,當緩沖區滿或調用 flush() 時,才會將數據寫入文件。
  • ?**write_all()**?:寫入字節數據。

三、按自定義分隔符讀取數據:split()

split() 可以將讀取的內容按指定的字節分隔符分割成多個片段。

示例:按換行符分割文件

use tokio::{fs::File, io::{AsyncBufReadExt, BufReader}, runtime};
?
fn main() {
    let rt = runtime::Runtime::new().unwrap();
    rt.block_on(async {
        let f = File::open("a.log").await.unwrap();
        let mut segments = BufReader::new(f).split(b'\n');
?
        while let Some(segment) = segments.next_segment().await.unwrap() {
            println!("segment: {}", String::from_utf8(segment).unwrap());
        }
    });
}

?解釋?:

  • ?**split(b'\n')**?:按換行符分割文件內容。
  • **每次調用 **next_segment() 獲取一個片段,返回 Vec<u8>

四、隨機讀寫文件:Seek

tokio::io::AsyncSeekExt 提供了 隨機讀寫 功能,可以設置文件的偏移位置,實現非順序的讀寫。

示例:設置偏移位置讀取文件

use std::io::SeekFrom;
use tokio::{fs::File, io::{AsyncReadExt, AsyncSeekExt}, runtime};
?
fn main() {
    let rt = runtime::Runtime::new().unwrap();
    rt.block_on(async {
        let mut f = File::open("a.log").await.unwrap();
?
        f.seek(SeekFrom::Start(5)).await.unwrap();  // 從第5個字節開始讀取
        let mut content = String::new();
        f.read_to_string(&mut content).await.unwrap();
        println!("Data: {}", content);
?
        f.rewind().await.unwrap();  // 將偏移指針重置到文件開頭
    });
}

?解釋?:

  • ?**seek()**?:將偏移指針移動到指定位置。
  • ?**rewind()**?:重置偏移指針到文件開頭。

五、標準輸入輸出

tokio::io 提供了 stdin() 和 ?**stdout()**?,用于異步讀取標準輸入和輸出。

示例:讀取用戶輸入并回顯

use tokio::{io::{AsyncReadExt, AsyncWriteExt}, runtime};
?
fn main() {
    let rt = runtime::Runtime::new().unwrap();
    rt.block_on(async {
        let mut stdin = tokio::io::stdin();
        let mut stdout = tokio::io::stdout();
?
        let mut buffer = vec![0; 1024];
        loop {
            stdout.write(b"Enter something: ").await.unwrap();
            stdout.flush().await.unwrap();
?
            let n = stdin.read(&mut buffer).await.unwrap();
            if n == 0 {
                break;  // 用戶輸入結束
            }
?
            stdout.write(&buffer[..n]).await.unwrap();
            stdout.flush().await.unwrap();
        }
    });
}

?解釋?:

  • ?讀取用戶輸入?:stdin.read() 從標準輸入讀取數據。
  • ?輸出到終端?:stdout.write() 將數據回顯。

六、全雙工通信:DuplexStream

tokio::io::duplex() 提供了類似套接字的全雙工管道,支持讀寫同時進行。

示例:模擬客戶端和服務端的通信

use tokio::{io::{self, AsyncReadExt, AsyncWriteExt}, runtime, time};
?
#[tokio::main]
async fn main() {
    let (mut client, mut server) = io::duplex(64);  // 創建雙向管道
?
    // 啟動一個任務:服務端發送消息
    tokio::spawn(async move {
        server.write_all(b"Hello from server").await.unwrap();
    });
?
    // 客戶端讀取來自服務端的消息
    let mut buf = vec![0; 64];
    let n = client.read(&mut buf).await.unwrap();
    println!("Client received: {}", String::from_utf8_lossy(&buf[..n]));
}

?解釋?:

  • ?**duplex()**?:創建全雙工讀寫管道。
  • ?客戶端和服務端通信?:服務端寫入數據,客戶端讀取數據。

七、拆分 Reader 和 Writer:split()

split() 方法可以將一個可讀寫的目標(如 TcpStream)拆分為 讀半部分 和 ?寫半部分?。

示例:拆分 DuplexStream

use tokio::{io::{self, AsyncReadExt, AsyncWriteExt}, runtime};
?
#[tokio::main]
async fn main() {
    let (client, server) = io::duplex(64);
?
    let (mut reader, writer) = io::split(client);  // 拆分為讀和寫部分
?
    // 關閉不使用的寫部分
    drop(writer);
?
    let mut buf = vec![0; 64];
    let n = reader.read(&mut buf).await.unwrap();
    println!("Read from server: {}", String::from_utf8_lossy(&buf[..n]));
}

八、總結

**在這一部分,教程介紹了如何使用 **Tokio 實現異步 IO,包括:

  1. ?**BufReaderBufWriter**?:用于高效的緩沖讀寫。
  2. ?w按行讀取和自定義分隔符?:方便處理文本數據。
  3. ?隨機讀寫文件?:通過設置偏移指針實現非順序讀寫。
  4. ?標準輸入輸出?:異步處理用戶輸入和終端輸出。
  5. ?全雙工通信?:通過 DuplexStream 實現雙向數據傳輸。
  6. ?拆分 Reader 和 Writer?:提高代碼的靈活性。w
文章來自個人專欄
文章 | 訂閱
0條評論
0 / 1000
請輸入你的評論
0
0