読み取りと書き込み
ファイルから文字列の行を読み込む
3行のメッセージをファイルに書き込み、その後、
BufRead::lines によって作成される Lines イテレータを使って、
1行ずつ読み戻します。File は Read を実装しており、それにより
BufReader トレイトが提供されます。File::create は書き込み用に
File を開き、File::open は読み込み用に開きます。
use std::fs::File;
use std::io::{Write, BufReader, BufRead, Error};
fn main() -> Result<(), Error> {
let path = "lines.txt";
let mut output = File::create(path)?;
write!(output, "Rust\n💖\nFun")?;
let input = File::open(path)?;
let buffered = BufReader::new(input);
for line in buffered.lines() {
println!("{}", line?);
}
Ok(())
}
同じファイルの読み書きを避ける
他のハンドルと等しいかどうかをテストできるファイルには
same_file::Handle を使用します。この例では、読み込み元のファイルと
書き込み先のファイルのハンドルが等しいかどうかをテストしています。
use same_file::Handle;
use std::io::{BufRead, BufReader, Error, ErrorKind, Write};
use std::fs::File;
use std::path::Path;
fn main() -> Result<(), Error> {
// テストファイルを作成する
let mut file = File::create("new.txt")?;
writeln!(file, "test content")?;
let path_to_read = Path::new("new.txt");
let stdout_handle = Handle::stdout()?;
let handle = Handle::from_path(path_to_read)?;
if stdout_handle == handle {
return Err(Error::new(
ErrorKind::Other,
"同じファイルを読み書きしています",
));
} else {
let file = File::open(&path_to_read)?;
let file = BufReader::new(file);
for (num, line) in file.lines().enumerate() {
println!("{} : {}", num, line?.to_uppercase());
}
}
Ok(())
}
メモリマップを使ってファイルにランダムアクセスする
memmap を使用してファイルのメモリマップを作成し、ファイルに対するいくつかの非連続な読み取りをシミュレートします。メモリマップを使うと、File 内で seek を繰り返し行う代わりに、単にスライスにインデックスを付けるだけで済みます。
Mmap::map 関数は、メモリマップの対象となるファイルが同時に別のプロセスによって変更されていないことを前提としています。そうでない場合、race condition が発生します。
use memmap::Mmap;
use std::fs::File;
use std::io::{Write, Error};
fn main() -> Result<(), Error> {
write!(File::create("content.txt")?, "My hovercraft is full of eels!")?;
let file = File::open("content.txt")?;
let map = unsafe { Mmap::map(&file)? };
let random_indexes = [0, 1, 2, 19, 22, 10, 11, 29];
assert_eq!(&map[3..13], b"hovercraft");
let random_bytes: Vec<u8> = random_indexes.iter()
.map(|&idx| map[idx])
.collect();
assert_eq!(&random_bytes[..], b"My loaf!");
Ok(())
}