Rust на примерах — страница 58 из 65

Rust предоставляет асинхронные каналы (channel) для взаимодействия между потоками. Каналы обеспечивают однонаправленную передачу информации между двумя конечными точками: отправителем (Sender) и получателем (Receiver).

use std::sync::mpsc::{Sender, Receiver};

use std::sync::mpsc;

use std::thread;

static NTHREADS: i32 = 3;

fn main() {

// Каналы имеют две конечные точки: Sender` и `Receiver`,

// где `T` - тип передаваемового сообщения.

// (аннотации типов избыточны)

let (tx, rx): (Sender, Receiver) = mpsc::channel();

let mut children = Vec::new();

for id in 0..NTHREADS {

// Отправитель может быть скопирован

let thread_tx = tx.clone();

// Каждый поток отправит через канал его id

let child = thread::spawn(move || {

// Поток забирает владение `thread_tx`

// Каждый поток добавляет своё сообщение в очередь канала

thread_tx.send(id).unwrap();

// Отправка - не блокирующая операция, поток незамедлительно

// продолжит работу после отправки сообщения

println!("поток {} завершён", id);

});

children.push(child);

}

// Здесь все сообщения собираются

let mut ids = Vec::with_capacity(NTHREADS as usize);

for _ in 0..NTHREADS {

// Метод `recv` "достаёт" сообщения из канала

// `recv` блокирует текущий поток, если доступных сообщений нет

ids.push(rx.recv());

}

// Ожидаем, когда потоки завершат всю оставшуюся работу

for child in children {

child.join().expect("Упс! Дочерний поток паникует");

}

// Посмотрите порядок, с которым сообщения были отправлeны

println!("{:?}", ids);

}

הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Path

Структура Path представляет пути к файлу в файловой системе. Есть два вида Path: posix::Path, для UNIX - подобных систем, и windows::Path, для Windows. В прелюдии экспортируется соответствующий платформозависимый вариант Path.

Path может быть создан из OsStr, и предоставляет некоторые методы для получения информации о файле или директории, на которые он указывает.

Обратите внимание, что внутренне представление Path не является UTF-8 строкой, но вместо этого хранит вектор байт (Vec). Следовательно, преобразование Path в &str не бесплатно и может закончиться неудачей (возвращается Option).

use std::path::Path;

fn main() {

// Создаём `Path` из `&'static str`

let path = Path::new(".");

// Метод `display` возвращает показываемую структуру

let _display = path.display();

// `join` соединяет `path` с байтовым контейнером, используя ОС-специфичный

// разделитель, и возвращает новый путь

let new_path = path.join("a").join("b");

// Конвертируем путь в строковый срез

match new_path.to_str() {

None => panic!("новый путь не является действительной UTF-8 последовательностью"),

Some(s) => println!("новый путь {}", s),

}

}

הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Не забудьте проверить остальные методы Path (posix::Path или windows::Path) и структуры Metadata.

Смотрите также:

OsStr и Metadata.

Файловый ввод-вывод

Структура File представляет открытый файл (она является обёрткой над файловым дескриптором) и даёт возможность чтения/записи этого файла.

Из-за того, что многие вещи могут пойти не так в процессе файлового ввода-вывода, все методы File возвращают тип io::Result, который является псевдонимом для Result.

Это делает явными ошибки всех операций ввода-вывода. Благодаря этому, программист может увидеть все пути отказов и обрабатывать их упреждающей форме.

open

Статический метод open может использоваться для открытия файла в режиме только для чтения.

Структура File владеет ресурсом, файловым дескриптором, и заботится о том, чтобы он был закрыт, когда структура удаляется из памяти.

use std::fs::File;

use std::io::prelude::*;

use std::path::Path;

fn main() {

// Создадим "путь" к нужному файлу

let path = Path::new("hello.txt");

let display = path.display();

// Откроем "путь" в режиме "только чтение". Возвращается `io::Result`

let mut file = match File::open(&path) {

Err(why) => panic!("невозможно открыть {}: {}", display, why),

Ok(file) => file,

};

// Читаем содержимое файла в строку. Метод возвращает `io::Result`

let mut s = String::new();

match file.read_to_string(&mut s) {

Err(why) => panic!("невозможно прочесть {}: {}", display, why),

Ok(_) => print!("{} содержит:\n{}", display, s),

}

// `file` выходит из области видимости и файл "hello.txt" закрывается

}

הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Вот ожидаемый результат:

$ echo "Hello World!" > hello.txt

$ rustc open.rs && ./open

hello.txt содержит:

Hello World!

(Рекомендуем протестировать предыдущий пример при различных условиях сбоев: файл hello.txt не существует или hello.txt не читаемый и другое)