» Rust快速入门 » 3. 标准库篇 » 3.2 标准库常用操作

标准库常用操作

线程

Rust 通过 std::thread 模块的 spawn 函数提供了一种生成线程的机制,该函数的参数是一个闭包。

use std::thread;

fn main() {
    // 生成一个新线程并打印1到5的数字
    let handle1 = thread::spawn(|| {
        for i in 1..=5 {
            println!("Thread 1: Count {}", i);
            thread::sleep(std::time::Duration::from_millis(200));
        }
    });

    // 生成另一个线程并打印从'A'到'E'的字母
    let handle2 = thread::spawn(|| {
        for ch in 'A'..'F' {
            println!("Thread 2: Letter {}", ch);
            thread::sleep(std::time::Duration::from_millis(300));
        }
    });

    // 等待两个线程完成
    handle1.join().unwrap();
    handle2.join().unwrap();

    println!("Main thread exiting.");
}

通道

在Rust中,通道是线程之间通过发送和接收消息进行通信的一种方式。

use std::thread;
use std::sync::mpsc; // mpsc代表多生产者,单消费者

fn main() {
    // 创建带有发送方和接收方的通道
    let (sender, receiver) = mpsc::channel();

    // 生成一个新线程以发送消息
    let sender_thread = thread::spawn(move || {
        for i in 1..=5 {
            // 向接收方发送消息
            sender.send(i).unwrap();
            thread::sleep(std::time::Duration::from_millis(200));
        }
    });

    // 主线程接收消息
    for _ in 1..=5 {
        // 从发送方接收消息
        let received_message = receiver.recv().unwrap();
        println!("Received: {}", received_message);
    }

    // 等待发送方线程完成
    sender_thread.join().unwrap();

    println!("Main thread exiting.");
}

路径

std::path::Path 类型用于表示文件系统路径。它提供了一种以平台无关的方式处理文件和目录路径的方法。

use std::path::Path;

fn main() {
    // 从字符串创建路径
    let path_str = "/home/user/documents/example.txt";
    let path = Path::new(path_str);

    // 显示路径组件
    println!("File Name: {:?}", path.file_name());
    println!("Parent Directory: {:?}", path.parent());
    println!("Extension: {:?}", path.extension());

    // 组合路径
    let new_path = path.join("subdirectory").join("newfile.txt");
    println!("Combined Path: {:?}", new_path);

    // 检查路径是否存在
    println!("Path exists: {}", path.exists());

    // 迭代路径组件
    println!("Path Components:");
    for component in path.components() {
        println!("{:?}", component);
    }
}

文件 I/O

File 结构体表示已打开的文件,并提供对底层文件的读取和写入访问。

use std::fs::File;
use std::io::{self, BufRead, BufReader, Write};

fn main() -> io::Result<()> {
    // File path
    let file_path = "example.txt";

    // 为写入创建文件
    let mut file = File::create(file_path)?;

    // 向文件写入一些内容
    writeln!(file, "Hello, Literank!")?;
    writeln!(file, "This is a second line.")?;

    // 为读取打开文件
    let file = File::open(file_path)?;

    // 从文件中读取并打印每一行
    let reader = BufReader::new(file);
    for line in reader.lines() {
        println!("{}", line?);
    }

    Ok(())
}

子进程

std::process::Command 用于生成子进程。

use std::process::Command;
use std::io;

fn main() -> io::Result<()> {
    // 要执行的命令: echo "Hello, LiteRank!"
    let command = Command::new("echo")
        .arg("Hello, LiteRank!")
        .output()?;

    // 检查命令是否成功
    if command.status.success() {
        // 将捕获的输出作为字符串打印
        let stdout_str = String::from_utf8_lossy(&command.stdout);
        println!("Output: {}", stdout_str);
    } else {
        // 打印错误消息
        let stderr_str = String::from_utf8_lossy(&command.stderr);
        eprintln!("Error: {}", stderr_str);
    }

    Ok(())
}

文件系统操作

std::fs 模块提供了各种常见文件系统操作的函数。

use std::fs::{self, File};
use std::io::{self, Read, Write};

fn main() -> io::Result<()> {
    // 创建目录
    fs::create_dir("literank_dir")?;

    // 检查路径是否存在
    let path_exists = fs::metadata("literank_dir").is_ok();
    println!("Does literank_dir exist? {}", path_exists);

    // 向文件写入内容
    let file_path = "literank_dir/example_file.txt";
    let mut file = File::create(file_path)?;
    write!(file, "Hello, Literank!")?;

    // 从文件中读取内容
    let mut buffer = String::new();
    let mut file = File::open(file_path)?;
    file.read_to_string(&mut buffer)?;
    println!("Content of {}: {}", file_path, buffer);

    // 重命名文件
    fs::rename(file_path, "literank_dir/renamed_file.txt")?;

    // 列出目录的内容
    println!("Contents of literank_dir:");
    for entry in fs::read_dir("literank_dir")? {
        if let Ok(entry) = entry {
            println!("{}", entry.file_name().to_string_lossy());
        }
    }

    // 删除文件
    fs::remove_file("literank_dir/renamed_file.txt")?;

    // 删除目录
    fs::remove_dir("literank_dir")?;

    Ok(())
}

程序参数

std::env::args 函数返回一个迭代器,该迭代器包含程序的命令行参数,其中可执行文件名被当作第一个参数。

use std::env;

fn main() {
    // 遍历命令行参数
    for (index, arg) in env::args().enumerate() {
        println!("Arg {} : {}", index, arg);
    }
}

FFI (外部函数接口)

Rust 中的外部函数接口(FFI)允许用户调用其他语言编写的函数,或被其他语言调用。

C文件(example.c)如下所示:

#include <stdio.h>

// 一个简单的C函数
void greet_from_c(const char *name) {
    printf("Hello, %s, from C!\n", name);
}

编译 C 代码:

$ gcc -c example.c -o example.o
$ gcc example.o -o libexample.so -shared

Rust文件(main.rs)如下所示:

// 定义与`libexample`库链接的 extern block(外部块)
#[link(name = "example")]
extern "C" {
    fn greet_from_c(name: *const std::os::raw::c_char);
}

fn main() {
    // 从 Rust 调用 C 函数
    let name = "Rust";
    unsafe {
        greet_from_c(name.as_ptr() as *const i8);
    }
}

编译Rust代码:

$ rustc main.rs

Rust 代码使用 extern "C" 来定义与 C 函数 greet_from_c 的接口。由于在 Rust 中调用外部函数被认为是不安全的,因此 unsafe 块是必需的。

代码挑战

尝试修改编辑器中的代码,使其打印:

Squared result: 1
Squared result: 4
Squared result: 9
Squared result: 16
Squared result: 25
Squared result: 36
Squared result: 49
Squared result: 64
Loading...
> 此处输出代码运行结果
上页
下页