MochiuWiki : SUSE, EC, PCB
案内
メインページ
最近の更新
おまかせ表示
MediaWiki についてのヘルプ
ツール
リンク元
関連ページの更新状況
特別ページ
ページ情報
We ask for
Donations
検索
個人用ツール
ログイン
Toggle dark mode
名前空間
ページ
議論
表示
閲覧
ソースを閲覧
履歴を表示
Rustの基礎 - ファイルのソースを表示
提供: MochiuWiki : SUSE, EC, PCB
←
Rustの基礎 - ファイル
あなたには「このページの編集」を行う権限がありません。理由は以下の通りです:
この操作は、次のグループのいずれかに属する利用者のみが実行できます:
管理者
、new-group。
このページのソースの閲覧やコピーができます。
== 概要 == ローカルに保存されたファイルからデータを読み込んだり、ファイルへデータを書き込むことができる。<br> 標準ライブラリの <code>std::fs</code> モジュールを使用して、ファイルの作成、読み込み、書き込み、削除などの操作を行うことができる。<br> <br><br> == ファイルのオープン / クローズ == ==== ファイルを開く ==== <code>std::fs::File</code> 構造体の <code>open</code> 関数を使用してファイルを開くことができる。<br> <syntaxhighlight lang="rust"> use std::fs::File; let file = File::open("myfile.txt"); </syntaxhighlight> <br> <code>open</code> メソッドは、<code>Result<File, std::io::Error></code> 型を返す。<br> 正常に開くことができる場合、<code>Ok(File)</code> を返す。<br> 正常に開くことができない場合、<code>Err(std::io::Error)</code> を返す。<br> <br> ファイルを開く際のモードを指定する場合は、<code>OpenOptions</code> 構造体を使用する。<br> <syntaxhighlight lang="rust"> use std::fs::OpenOptions; let file = OpenOptions::new() .read(true) .write(true) .open("myfile.txt"); </syntaxhighlight> <br> <code>OpenOptions</code> 構造体では以下に示すオプションを指定できる。<br> * read(true) *: 読み込み用 * write(true) *: 書き込み用 * append(true) *: 追記用 (ファイルの末尾に追加) * truncate(true) *: ファイルの中身をクリア * create(true) *: ファイルが存在しない場合は作成 * create_new(true) *: ファイルが存在しない場合のみ作成 (存在する場合はエラー) <br> 以下の例では、様々なモードでファイルを開いている。<br> <syntaxhighlight lang="rust"> use std::fs::File; use std::fs::OpenOptions; // 読み込み専用 let f1 = File::open("myfile.txt"); // 読み書き可能 let f2 = OpenOptions::new() .read(true) .write(true) .open("myfile.txt"); // 書き込み専用(ファイルの中身をクリア) let f3 = OpenOptions::new() .write(true) .truncate(true) .create(true) .open("myfile.txt"); // 追記モード let f4 = OpenOptions::new() .append(true) .create(true) .open("myfile.txt"); </syntaxhighlight> <br> エラー処理を行う場合は、<code>match</code> 式 や <code>unwrap</code>、<code>expect</code> メソッドを使用する。<br> <syntaxhighlight lang="rust"> use std::fs::File; // matchを使用する場合 let file = match File::open("myfile.txt") { Ok(file) => file, Err(error) => panic!("ファイルを開けません: {:?}", error), }; // unwrapを使用する場合 let file = File::open("myfile.txt").unwrap(); // expectを使用する場合 let file = File::open("myfile.txt").expect("ファイルを開けません"); </syntaxhighlight> <br> ==== ファイルを閉じる ==== Rustでは、変数がスコープを抜けると自動的にファイルが閉じられる。<br> これは、<code>File</code> 構造体が <code>Drop</code> トレイトを実装しているためである。<br> <syntaxhighlight lang="rust"> use std::fs::File; { let file = File::open("myfile.txt").unwrap(); // ファイルを使用する処理 // ...略 } // ここでfileがスコープを抜け、自動的にクローズされる </syntaxhighlight> <br> 明示的にファイルを閉じる必要がある場合は、<code>drop</code> メソッドを使用する。<br> <syntaxhighlight lang="rust"> use std::fs::File; let file = File::open("myfile.txt").unwrap(); // ファイルを使用する処理 drop(file); // 明示的にクローズ </syntaxhighlight> <br><br> == テキストファイルの読み込み == ==== 全体を読み込む (read_to_stringメソッド) ==== ファイルに含まれるテキストを全て読み込む場合、<code>std::fs::read_to_string</code> メソッドを使用する。<br> <syntaxhighlight lang="rust"> use std::fs; let contents = fs::read_to_string("myfile.txt") .expect("ファイルの読み込みに失敗しました"); println!("{}", contents); </syntaxhighlight> <br> または、<code>File</code> と <code>Read</code> トレイトを使用する方法もある。<br> <syntaxhighlight lang="rust"> use std::fs::File; use std::io::Read; let mut file = File::open("myfile.txt").unwrap(); let mut contents = String::new(); file.read_to_string(&mut contents).unwrap(); println!("{}", contents); </syntaxhighlight> <br> ==== 行単位で読み込む (BufReaderとlines) ==== ファイルから1行ずつファイルの内容を読み込む場合、<code>BufReader</code> と <code>lines</code>メソッドを使用する。<br> <syntaxhighlight lang="rust"> use std::fs::File; use std::io::{BufRead, BufReader}; let file = File::open("myfile.txt").unwrap(); let reader = BufReader::new(file); for line in reader.lines() { let line = line.unwrap(); println!("{}", line); } </syntaxhighlight> <br> <code>lines</code> メソッドは、各行の末尾の改行文字を自動的に取り除く。<br> エラー処理を含めた実装例は以下の通りである。<br> <syntaxhighlight lang="rust"> use std::fs::File; use std::io::{BufRead, BufReader}; let file = File::open("myfile.txt").expect("ファイルを開けません"); let reader = BufReader::new(file); for line in reader.lines() { match line { Ok(content) => println!("{}", content), Err(error) => eprintln!("行の読み込みエラー: {}", error), } } </syntaxhighlight> <br> 改行文字を含めて読み込みたい場合は、<code>read_line</code> メソッドを使用する。<br> <syntaxhighlight lang="rust"> use std::fs::File; use std::io::{BufRead, BufReader}; let file = File::open("myfile.txt").unwrap(); let mut reader = BufReader::new(file); let mut line = String::new(); while reader.read_line(&mut line).unwrap() > 0 { print!("{}", line); // 改行が含まれる line.clear(); } </syntaxhighlight> <br> ==== 行単位で分割してベクターとして取得する ==== ファイル全体の読み込み後、読み込みしたデータを行単位で分割して、<code>Vec</code> の要素として追加することができる。<br> <syntaxhighlight lang="rust"> use std::fs::File; use std::io::{BufRead, BufReader}; let file = File::open("myfile.txt").unwrap(); let reader = BufReader::new(file); let lines: Vec<String> = reader .lines() .map(|line| line.unwrap()) .collect(); for line in &lines { println!("{}", line); } </syntaxhighlight> <br> エラー処理を適切に行う場合は、以下に示すように実装する。<br> <syntaxhighlight lang="rust"> use std::fs::File; use std::io::{BufRead, BufReader}; let file = File::open("myfile.txt").expect("ファイルを開けません"); let reader = BufReader::new(file); let lines: Result<Vec<String>, _> = reader.lines().collect(); match lines { Ok(lines) => { for line in lines { println!("{}", line); } } Err(error) => eprintln!("読み込みエラー: {}", error), } </syntaxhighlight> <br><br> == テキストファイルの書き込み == テキストファイルへ書き込むためにファイルを開く場合、<code>OpenOptions</code> を使用して適切なモードを指定する。<br> <syntaxhighlight lang="rust"> use std::fs::OpenOptions; // 書き込み専用 (上書き) let f1 = OpenOptions::new() .write(true) .truncate(true) .create(true) .open("myfile.txt"); // 追記モード let f2 = OpenOptions::new() .append(true) .create(true) .open("myfile.txt"); // 新規作成のみ let f3 = OpenOptions::new() .write(true) .create_new(true) .open("myfile.txt"); </syntaxhighlight> <br> ==== 書き込み / 上書き ==== ファイルに書き込む場合、ファイルが存在しない時はファイルを新規作成、ファイルが存在する時は上書きする。<br> <br> テキストファイルに書き込む場合は、<code>write</code> メソッド または <code>write_all</code>メソッドを使用する。<br> <syntaxhighlight lang="rust"> use std::fs::OpenOptions; use std::io::Write; let mut file = OpenOptions::new() .write(true) .truncate(true) .create(true) .open("myfile.txt") .unwrap(); file.write_all(b"Hello, World!\n").unwrap(); </syntaxhighlight> <br> 文字列を書き込む場合は、<code>as_bytes()</code> メソッドでバイト列に変換するか、<code>write!</code> マクロを使用する。<br> <syntaxhighlight lang="rust"> use std::fs::OpenOptions; use std::io::Write; let mut file = OpenOptions::new() .write(true) .truncate(true) .create(true) .open("myfile.txt") .unwrap(); // as_bytesメソッドを使用 file.write_all("こんにちは\n".as_bytes()).unwrap(); // write!マクロを使用 write!(file, "お元気ですか?\n").unwrap(); </syntaxhighlight> <br> 簡潔に書き込む場合は、<code>std::fs::write</code> メソッドを使用する。<br> <syntaxhighlight lang="rust"> use std::fs; fs::write("myfile.txt", "こんにちは\n").expect("書き込みに失敗しました"); </syntaxhighlight> <br> 複数の文字列をまとめてファイルに書き込む場合は、ベクターをループで処理する。<br> <syntaxhighlight lang="rust"> use std::fs::OpenOptions; use std::io::Write; let mut file = OpenOptions::new() .write(true) .truncate(true) .create(true) .open("myfile.txt") .unwrap(); let datalist = vec!["こんにちは\n", "お元気ですか?\n", "それではまた\n"]; for data in datalist { file.write_all(data.as_bytes()).unwrap(); } </syntaxhighlight> <br> ==== 追記 ==== ファイルに追記する場合、ファイルが存在しない時はファイルを新規作成、ファイルが存在する時はファイルの最後に追記する。<br> <syntaxhighlight lang="rust"> use std::fs::OpenOptions; use std::io::Write; let mut file = OpenOptions::new() .append(true) .create(true) .open("myfile.txt") .unwrap(); file.write_all("こんにちは\n".as_bytes()).unwrap(); let datalist = vec!["お元気ですか?\n", "それではまた\n"]; for data in datalist { file.write_all(data.as_bytes()).unwrap(); } </syntaxhighlight> <br> ==== ファイルを新規作成して書き込む ==== ファイルが存在しない場合のみファイルを新規作成して書き込む場合、<code>create_new(true)</code> メソッドを使用する。<br> ファイルが存在する場合は、エラーが発生する。<br> <syntaxhighlight lang="rust"> use std::fs::OpenOptions; use std::io::Write; let mut file = OpenOptions::new() .write(true) .create_new(true) .open("myfile.txt") .expect("ファイルが既に存在します"); file.write_all("こんにちは\n".as_bytes()).unwrap(); let datalist = vec!["お元気ですか?\n", "それではまた\n"]; for data in datalist { file.write_all(data.as_bytes()).unwrap(); } </syntaxhighlight> <br><br> == バイナリファイル == バイナリファイルを読み込む場合、<code>File::open</code> メソッドを使用してファイルを開く。<br> Rustでは、テキストモードとバイナリモードの区別はなく、全てのファイルはバイナリとして扱われる。<br> <syntaxhighlight lang="rust"> use std::fs::File; let file = File::open("myfile.dat").unwrap(); </syntaxhighlight> <br> バイナリファイルのデータを読み込む場合、<code>read</code> メソッドを使用する。<br> <syntaxhighlight lang="rust"> use std::fs::File; use std::io::Read; let mut file = File::open("myfile.dat").unwrap(); let mut buffer = Vec::new(); file.read_to_end(&mut buffer).unwrap(); println!("{:?}", buffer); </syntaxhighlight> <br> 指定したバイト数だけ読み込む場合は、固定サイズのバッファを使用する。<br> <syntaxhighlight lang="rust"> use std::fs::File; use std::io::Read; let mut file = File::open("myfile.dat").unwrap(); let mut buffer = [0u8; 1024]; // 1024バイトのバッファ let bytes_read = file.read(&mut buffer).unwrap(); println!("読み込んだバイト数: {}", bytes_read); </syntaxhighlight> <br> 簡潔にファイル全体を読み込む場合は、<code>std::fs::read</code> メソッドを使用する。<br> <syntaxhighlight lang="rust"> use std::fs; let data = fs::read("myfile.dat").expect("ファイルの読み込みに失敗しました"); println!("{:?}", data); </syntaxhighlight> <br> バイナリファイルにデータを書き込む場合、<code>write</code> メソッド または <code>write_all</code> メソッドを使用する。<br> <syntaxhighlight lang="rust"> use std::fs::File; use std::io::Write; let mut file = File::create("myfile.dat").unwrap(); file.write_all(b"ABCDEFG").unwrap(); </syntaxhighlight> <br> 簡潔に書き込む場合は、<code>std::fs::write</code> メソッドを使用する。<br> <syntaxhighlight lang="rust"> use std::fs; fs::write("myfile.dat", b"ABCDEFG").expect("書き込みに失敗しました"); let data = fs::read("myfile.dat").unwrap(); println!("{:?}", data); // 出力 [65, 66, 67, 68, 69, 70, 71] </syntaxhighlight> <br> 以下の例では、画像ファイルを読み込み、読み込んだデータを新規作成したバイナリファイルに書き込んでいる。<br> <syntaxhighlight lang="rust"> use std::fs; use std::io::{Read, Write}; // 方法1 : 1度に全て読み書き let data = fs::read("Sample1.png").expect("読み込みエラー"); fs::write("Sample2.png", data).expect("書き込みエラー"); // 方法2 : バッファを使用して1バイトずつ処理 use std::fs::File; let mut fr = File::open("Sample1.png").unwrap(); let mut fw = File::create("Sample2.png").unwrap(); let mut buffer = [0u8; 1]; loop { let bytes_read = fr.read(&mut buffer).unwrap(); if bytes_read == 0 { break; } fw.write_all(&buffer[..bytes_read]).unwrap(); } </syntaxhighlight> <br><br> == ファイルの作成 / 削除 == ==== ファイルの作成 ==== 空のファイルを新規作成する場合は、<code>File::create</code> メソッドを使用する。<br> <syntaxhighlight lang="rust"> use std::fs::File; let file = File::create("user.txt").expect("ファイルの作成に失敗しました"); </syntaxhighlight> <br> <code>File::create</code> メソッドは、ファイルが存在しない場合は新規作成し、存在する場合は内容を空にする。<br> <br> ファイルが存在しない場合のみ作成したい場合は、<code>OpenOptions</code> を使用する。<br> <syntaxhighlight lang="rust"> use std::fs::OpenOptions; let file = OpenOptions::new() .write(true) .create_new(true) .open("user.txt") .expect("ファイルが既に存在するか、作成に失敗しました"); </syntaxhighlight> <br> ==== ファイルの削除 ==== ファイルを削除する場合は、<code>std::fs::remove_file</code> メソッドを使用する。<br> <syntaxhighlight lang="rust"> use std::fs; fs::remove_file("name.txt").expect("ファイルの削除に失敗しました"); </syntaxhighlight> <br> 存在しないファイルを削除しようとすると、エラーが発生する。<br> エラーを無視する場合は、以下のように実装する。<br> <syntaxhighlight lang="rust"> use std::fs; match fs::remove_file("name.txt") { Ok(_) => println!("ファイルを削除しました"), Err(e) => eprintln!("削除エラー: {}", e), } // または、Result型を無視 let _ = fs::remove_file("name.txt"); </syntaxhighlight> <br><br> == ファイルの存在確認 == 指定したパスが示すファイルが存在するかどうかを確認する場合、<code>std::path::Path</code> の <code>exists</code> メソッドを使用する。<br> <syntaxhighlight lang="rust"> use std::path::Path; let path = Path::new("myfile.txt"); if path.exists() { println!("ファイルは存在します"); } else { println!("ファイルは存在しません"); } </syntaxhighlight> <br> <code>exists</code> メソッドは、ファイルまたはディレクトリが存在する場合に <code>true</code> を返すことに注意する。<br> <br> ファイルとディレクトリを判別する場合は、<code>is_file</code> メソッド と <code>is_dir</code> メソッドを使用する。<br> <syntaxhighlight lang="rust"> use std::path::Path; let path = Path::new("myfile.txt"); if path.is_file() { println!("これはファイルです"); } else if path.is_dir() { println!("これはディレクトリです"); } else { println!("存在しません"); } </syntaxhighlight> <br> ファイルのメタデータを取得して詳細な情報を確認することもできる。<br> <syntaxhighlight lang="rust"> use std::fs; match fs::metadata("myfile.txt") { Ok(metadata) => { if metadata.is_file() { println!("ファイルです。サイズ: {} バイト", metadata.len()); } else if metadata.is_dir() { println!("ディレクトリです"); } } Err(_) => println!("ファイルは存在しません"), } </syntaxhighlight> <br><br> == ファイル名の変更 == ファイル名を変更する場合は、<code>std::fs::rename</code> メソッドを使用する。<br> <syntaxhighlight lang="rust"> use std::fs; fs::rename("book.txt", "memo.txt").expect("リネームに失敗しました"); </syntaxhighlight> <br> ファイルを別のディレクトリに移動することもできる。<br> <syntaxhighlight lang="rust"> use std::fs; fs::rename("book.txt", "back/memo.txt").expect("移動に失敗しました"); </syntaxhighlight> <br> 移動先のディレクトリが存在しない場合、エラーが発生する。<br> <br> エラー処理を含めた実装例は以下の通りである。<br> <syntaxhighlight lang="rust"> use std::fs; match fs::rename("book.txt", "memo.txt") { Ok(_) => println!("リネームに成功しました"), Err(error) => eprintln!("リネームエラー: {}", error), } </syntaxhighlight> <br> Windows環境では、移動先のファイルが既に存在する場合、エラーが発生する。<br> Unix系では、既存のファイルを上書きする。<br> <syntaxhighlight lang="rust"> use std::fs; // 既にmemo.txtが存在する場合の動作はOSに依存 fs::rename("book.txt", "memo.txt").expect("リネームに失敗しました"); </syntaxhighlight> <br><br> == 条件に一致するファイルの一覧の取得 == ==== 同階層のファイルの一覧の取得 ==== 指定した条件に一致するファイルの一覧を取得する場合は、<code>glob</code> クレートを使用する。<br> <br> まず、Cargo.tomlファイルに依存関係を追加する。<br> <syntaxhighlight lang="toml"> [dependencies] glob = "0.3" </syntaxhighlight> <br> <code>glob</code> メソッドを使用してパターンマッチングを行う。<br> <syntaxhighlight lang="rust"> use glob::glob; for entry in glob("*.txt").expect("パターンの読み込みに失敗しました") { match entry { Ok(path) => println!("{:?}", path), Err(e) => eprintln!("エラー: {}", e), } } </syntaxhighlight> <br> パターンには以下の特殊文字を指定できる。<br> * <nowiki>*</nowiki> *: 0文字以上の任意の文字 * ? *: 1文字の任意の文字 * [abc] *: 括弧の中のいずれかの文字 <br> 以下の例では、末尾が.jpgのファイルを取得している。<br> <syntaxhighlight lang="rust"> use glob::glob; for entry in glob("test/*.jpg").unwrap() { if let Ok(path) = entry { println!("{}", path.display()); } } </syntaxhighlight> <br> 以下の例では、bから始まるファイルを取得している。<br> <syntaxhighlight lang="rust"> use glob::glob; for entry in glob("test/b*").unwrap() { if let Ok(path) = entry { println!("{}", path.display()); } } </syntaxhighlight> <br> 以下の例では、3文字の任意の文字で始まり、末尾が.txtのファイルを取得している。<br> <syntaxhighlight lang="rust"> use glob::glob; for entry in glob("test/???.txt").unwrap() { if let Ok(path) = entry { println!("{}", path.display()); } } </syntaxhighlight> <br> 以下の例では、文字の範囲を指定している。<br> <syntaxhighlight lang="rust"> use glob::glob; // aからeまでの文字で始まり、末尾が.txtのファイル for entry in glob("test/[a-e]*.txt").unwrap() { if let Ok(path) = entry { println!("{}", path.display()); } } // fからzまでの文字で始まり、末尾が.txtのファイル for entry in glob("test/[f-z]*.txt").unwrap() { if let Ok(path) = entry { println!("{}", path.display()); } } </syntaxhighlight> <br> ==== 再帰的にファイルの一覧の取得 ==== サブディレクトリを含めて再帰的にファイルを検索する場合、パターンに <code>**</code> を使用する。<br> <syntaxhighlight lang="rust"> use glob::glob; for entry in glob("test/**/*.txt").unwrap() { if let Ok(path) = entry { println!("{}", path.display()); } } // 出力例 // test/book.txt // test/cup.txt // test/pen.txt // test/doc/sample.txt // test/back/2020.txt // test/back/old/2017.txt </syntaxhighlight> <br> 標準ライブラリのみを使用する場合は、<code>std::fs::read_dir</code> メソッドを再帰的に呼び出す。<br> <syntaxhighlight lang="rust"> use std::fs; use std::path::Path; fn visit_dirs(dir: &Path, ext: &str) -> std::io::Result<()> { if dir.is_dir() { for entry in fs::read_dir(dir)? { let entry = entry?; let path = entry.path(); if path.is_dir() { visit_dirs(&path, ext)?; } else if let Some(extension) = path.extension() { if extension == ext { println!("{}", path.display()); } } } } Ok(()) } fn main() { visit_dirs(Path::new("test"), "txt").unwrap(); } </syntaxhighlight> <br><br> __FORCETOC__ [[カテゴリ:Rust]]
Rustの基礎 - ファイル
に戻る。
案内
メインページ
最近の更新
おまかせ表示
MediaWiki についてのヘルプ
ツール
リンク元
関連ページの更新状況
特別ページ
ページ情報
We ask for
Donations
Collapse