Rustでstd::process::Commandを使ってみたらコマンドプロンプトの文字コードにハマった話

今回は表題の通り、Rustでstd::process::Commandを使って簡単な外部コマンドを実行してみようと挑戦した時のことを書き残します。

ちなみに、私の環境はwindowsです。

Rustでは標準ライブラリとして外部コマンド(windowsだとコマンドプロントを通して使う"dir"や"tree"などのコマンド)を実行することができるということなので、実際にこのライブラリの使い方を公式のドキュメントで確認して実行してみます。

use std::process::Command;

fn main() {
    let output = Command::new("cmd")
        .args(&["/C", "echo hello_ワールド"])
        .output()
        .expect("failed to execute process");
    println!("{:?}", output);
}

上記のようにしてcargo runを実行すると、下記のような出力が出てきます!!上手く実行できたようです。

Output { status: ExitStatus(ExitStatus(0)), stdout: [104, 101, 108, 108, 111, 95, 131, 143, 129, 91, 131, 139, 131, 104, 13, 10], stderr: "" }

ちなみに、.args~の所を、例えば.args(&["echo hello_ワールド"])のように第一引数をなくすと上手く実行されません。正確にはコマンドプロントを開いた直後に出てくる文字がstdout部分に出力されるだけです)。なので忘れないようにしましょう

さて、今はprintln!で色々出力されているのでstdoutの欲しい部分だけ出力されるようにしたいので、println!の部分を以下のように書き換えます

use std::process::Command;

fn main() {
    let output = Command::new("cmd")
        .args(&["/C", "echo hello_ワールド"])
        .output()
        .expect("failed to execute process");
    println!("{}", String::from_utf8_lossy(&output.stdout));  // この行を変更
}
}

こうすることで無事stdoutの部分だけを出力できた。。。と思いきや日本語が文字化けしてしまいました。

さて、何故か、、、と思って調べてみるとどうもコマンドプロントの文字コードに問題があるようでした。

https://www.javadrive.jp/command/display/index5.html

上記に従い、chcp 65001文字コードUTF-8に変更して再度実行してみると、無事実行できました。めでたしめでたし