Rustでのファイル操作まとめ!基本操作から大量データの扱いまで

2024年3月23日土曜日

Rust

t f B! P L

RUST

Rustでのファイル操作は、標準ライブラリのstd::fsstd::ioモジュールを使用して行います。これらのモジュールはファイルの読み書きやメタデータの操作など、基本的なファイルシステムの操作をサポートしています。ここでは、指定された内容に沿って、Rustでのファイル操作についての記事を構成する方法を説明します。

ファイルの存在チェック

Rustでファイルが存在するかどうかをチェックするには、std::path::Pathexists関数を使用します。

use std::path::Path;

fn check_file() {
    
    if Path::new("path/to/file").exists() {
        println!("ファイルあったよ!");
    } else {
        println!("ファイル無いよ");
    }
}

テキストファイルの読み込み

小規模なテキストファイルを読み込む最もシンプルな方法は、std::fs::read_to_string関数を使用することです。この関数は、指定されたパスのファイル全体を文字列として読み込みます。

use std::fs;

fn read_from_file() {

    let f = fs::read_to_string("path/to/file");
    match f {
        Ok(contents) => {
            println!("{}", contents)
        },
        Err(error) => {
            panic!("エラー: {:?}", error)
        },
    };
}

大量データのテキストファイル読み込み(バッファリング)

大量のデータを含むファイルを扱う場合は、バッファリングを使用してメモリ使用量を最適化します。std::io::BufReaderを使用してファイルを読み込みます。これにより、データを小さなチャンクで読み込むことができ、大量のデータを効率的に処理できます。

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

fn read_from_file() -> io::Result<()> {
    let file = File::open("output.txt")?;
    let reader = BufReader::new(file);
    
    for line in reader.lines() {
        println!("{}", line.unwrap());
    }

    Ok(())
}

テキストファイルの書き込み

ファイルへのテキストの書き込みには、std::fs::Filestd::io::Writeトレイトを使用します。File::create関数で新しいファイルを作成(または既存のファイルを上書き)し、write_allメソッドを使用してデータを書き込みます。

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

fn write_to_file() -> std::io::Result<()> {
    let mut file = File::create("path/to/file")?;
    file.write_all("ファイルの中身".as_bytes())
}

大量データのテキストファイル書き込み(バッファリング)

大量のデータを書き込む場合は、バッファリングを使用してメモリ使用量を最適化します。std::io::BufWriterを使用してファイルを書き込みます。std::io::BufWriterは、同じファイルまたはネットワーク ソケットに対して小規模な繰り返し書き込み呼び出しを行うプログラムの速度を向上させることができます。

fn write_to_file() -> std::io::Result<()> {
    let file = File::create("writetest2.txt")?;
    let mut f = BufWriter::new(file);

    for i in 0 .. 100_000 {
        let contents = format!("{0: <08}\n", i);
        f.write(contents.as_bytes()).unwrap();
    }

    return Ok(());
}

CSVファイルの読み込み

CSVファイルを読み込む方法には様々なアプローチがあり、多くの外部パッケージが存在しますが、ここではRustの標準CSVパッケージを用いた読み込み方法に焦点を当てます。

CSVパッケージの追加

RustプロジェクトでCSVファイルを扱うには、まずCargo.tomlファイルにCSVパッケージを追加する必要があります。

[dependencies]
csv = "1.3.0"

CSVファイルの読み込み方

CSVファイルの読み込みにはcsv::Readerを使用します。Reader::from_path関数を利用して、読み込むCSVファイルのパスを指定し、リーダーを作成します。その後、for文を用いてファイル内のレコードを順番に処理します。

fn read_csv() -> Result<(), Box<dyn Error>> {
    let mut rdr = csv::Reader::from_path("path/to/file.csv")?;
    for result in rdr.records() {
        let record = result?;
        println!("1列目の値: {}", &record[0]);
        println!("2列目の値: {}", &record[1]);
    }
    Ok(())
}

大量のCSVデータを読み込んでも大丈夫?

CSVファイルから大量のデータを効率的に読み込む場合、RustのCSVライブラリは高いパフォーマンスを提供します。内部的には、ライブラリはストリーミング読み込みをサポートしており、ファイル全体を一度にメモリに読み込むのではなく、必要に応じて少しずつデータを処理します。これにより、大きなCSVファイルでもメモリの消費を抑えつつ、データを効率的に扱うことが可能です。

CSVファイルの書き込み

前述の読み込みでも使った、標準CSVパッケージを使ってCSVを書き込む方法を紹介します。

fn write_csv() -> Result<(), Box<dyn Error>> {
    
    let file_out = std::fs::File::options()
        .write(true)
        .create(true)
        .open("sample.csv")
        .expect("csvの書き込み失敗");

    let mut wtr = csv::Writer::from_writer(&file_out);

    // CSVヘッダーを書き込む
    wtr.write_record(&["City", "State", "Population"])?;

    // CSVレコードを書き込む
    wtr.write_record(&["Boston", "Massachusetts", "692600"])?;
    wtr.write_record(&["Concord", "New Hampshire", "42695"])?;

    // データをフラッシュして確実に書き込む
    wtr.flush()?;

    return Ok(());
}

このコードは、以下のステップに分けられます。

1. ファイルの準備

まず、std::fs::File::options()を使用してファイルを開くオプションを設定します。この例では、ファイルが存在しない場合は新規作成され(.create(true))、書き込みモードで開かれます(.write(true))。そして、"sample.csv"という名前のファイルを開きます。ファイルのオープンに失敗した場合は、"csvの書き込み失敗"というメッセージと共にパニックが発生します。

2. CSVライターの準備

次に、csv::Writer::from_writerメソッドを使用して、先ほど開いたファイルに対するCSVライターインスタンスを生成します。このインスタンスを通じて、CSVデータの書き込みを行います。

3. ヘッダーの書き込み

write_recordメソッドを使用して、CSVファイルの最初の行としてヘッダーを書き込みます。この例では、ヘッダーとして[“City”, “State”, “Population”]の3つの列名を使用しています。

4. レコードの書き込み

同じくwrite_recordメソッドを用いて、具体的なデータレコードをCSVファイルに書き込みます。この例では、2つの都市(“Boston”, “Massachusetts”, “692600"と"Concord”, “New Hampshire”, “42695”)のデータを追加しています。

5. データのフラッシュ

最後に、wtr.flush()を呼び出して、バッファに残っているデータをファイルにフラッシュ(確実に書き込み)します。これにより、すべてのデータがファイルに正しく保存されることを保証します。

スポンサーリンク
スポンサーリンク

このブログを検索

Profile

自分の写真
Webアプリエンジニア。 日々新しい技術を追い求めてブログでアウトプットしています。
プロフィール画像は、猫村ゆゆこ様に書いてもらいました。

仕事募集もしていたり、していなかったり。

QooQ