NnmnLog

Rustでファイルを開く

作成: 2021-02-12
更新: 2021-02-12
タグ: Rust Programming

Rustでファイルを操作して、書き込んだり読み込んだりする方法です。

以下について、簡単なコードを添えて書いています。

  • ファイルを新規作成して書き込みする
  • ファイルを開き、内容を読み込む
  • 読み込みと書き込みを行う
  • まとめ

ファイルを新規作成して書き込みする

std::fs::File::createを使ってファイルを作成してます。

作成したファイルへの書き込みは、write_allを使って行っています。

use std::fs::File;
use std::io::Write;

fn main() {
    let filename = "hello.txt";

    // 複数回実行した場合上書きされる
    let mut file = match File::create(filename) {
        Err(why) => panic!("Couldn't create {}: {}", filename, why),
        Ok(file) => file,
    };

    let contents = "こんにちは、Rust!";
    match file.write_all(contents.as_bytes()) {
        Err(why) => panic!("Couldn't write \"{}\" to {}: {}", contents, filename, why),
        Ok(_) => println!("finished"),
    }
}

hello.txtというファイルがソースコードと同じディレクトリに作成され、こんにちは、Rust!という文字列がファイルに書き込まれます。

ファイルを開き、内容を読み込む

ファイルの読み込みは、File::openを使って開いたファイルに対して、read_to_stringを実行します。

read_to_stringの引数に読み込んだ文字列を格納する変数の参照を渡すことで、その変数にファイルの中身が書き込まれます。

use std::fs::File;
use std::io::Read;

fn main() {
    let filename = "hello.txt";

    let mut file = match File::open(filename) {
        Err(why) => panic!("Couldn't open {}: {}", filename, why),
        Ok(file) => file,
    };

    let mut contents = String::new();
    match file.read_to_string(&mut contents) {
        Err(why) => panic!("Couldn't read {}: {}", filename, why),
        Ok(_) => (),
    }
    println!("contents: {}", contents);
}

読み込みと書き込みを行う

std::fs::OpenOptionsを使うことで、もう少し細かくファイルの読み書きを制御することができます。

OpenOptionsのオブジェクトを作成して、ファイルを開く設定を行います。

以下の例では、ファイルがなければ新規作成し、読み込みと書き込み+追記可能な設定でファイルを開きます。

ファイル内容を標準出力に出した後、ファイルに1行追記するので、実行するたびにhello.txtの行が増えていきます。

use std::fs::OpenOptions;
use std::io::Read;
use std::io::Write;

fn main() {
    let filename = "hello.txt";

    // OpenOptionsでファイルの開き方を制御
    let mut file = match OpenOptions::new()
        .create(true)
        .write(true)
        .read(true)
        .append(true)
        .open(filename)
    {
        Err(why) => panic!("Couldn't open {}: {}", filename, why),
        Ok(file) => file,
    };

    let mut contents = String::new();
    match file.read_to_string(&mut contents) {
        Err(why) => panic!("Couldn't read {}: {}", filename, why),
        Ok(_) => (),
    }
    println!("contents:\n{}", contents);

    let contents = "こんにちは、Rust!\n";
    match file.write_all(contents.as_bytes()) {
        Err(why) => panic!("Couldn't write \"{}\" to {}: {}", contents, filename, why),
        Ok(_) => println!("finished"),
    }
}

設定とOpenOptionsのメソッドと意味の対応は以下になります。

  • .create(true): ファイルを作成
  • .write(true): 書き込み可能
  • .read(true): 読み込み可能
  • append(true): 追記する
  • open(<ファイル名>): <ファイル名>を開く

File::createで読み込もうとすると、エラーになる

File::createで開いたファイルは書き込み専用なので、読み込もうとするとエラーになります。

同様に、File::openで開いたファイルは、読み込み専用なので、書き込もうとするとエラーになります。

use std::fs::File;
use std::io::Read;

fn main() {
    let filename = "hello.txt";

    let mut file = match File::create(filename) {
        Err(why) => panic!("Couldn't create {}: {}", filename, why),
        Ok(file) => file,
    };

    // File::createは書き込み専用で開くのでエラーになる
    //   => "thread 'main' panicked at 'Couldn't read hello.txt: Bad file descriptor (os error 9)', src/main.rs:22:21"
    let mut contents = String::new();
    match file.read_to_string(&mut contents) {
        Err(why) => panic!("Couldn't read {}: {}", filename, why),
        Ok(_) => println!("finished"),
    }
}

まとめ

  • File::createは書き込み専用でファイルを開く
  • File::openは読み込み専用でファイルを開く
  • File::createで複数回開くと上書きされる
  • 細かいファイルの開き方の指定は、OpenOptionsを使って指定する

Rustでのファイルの開き方がなんとなくわかりました。

createで書き込み専用で開くのは、初めてで一瞬戸惑いましたが、確かに新規でファイル作成した時に読み込むケースは少ないと思うので、わかりやすくて良いなぁと思いました。