試作品
Shift_JISのテキストファイルを読み込み、UTF-8に変換~保存するプログラムをRustで書いた。
use encoding_rs;
use std::fs;
use std::io::Write;
fn main() {
// 読み込むファイルパスの設定
let path = "test_sj.txt";
// 出力先ファイルパスの設定
let mut file = fs::File::create("output.txt").unwrap();
// 読み込み
let s = fs::read(path).unwrap();
// Shift_JISのバイト列(Vec<u8>) を UTF-8の文字列(String) に変換
let (res, _, _) = encoding_rs::SHIFT_JIS.decode(&s);
let text = res.into_owned();
// 出力
file.write(text.as_bytes()).unwrap();
}
要点
- UTF-8以外の文字コードは文字列(
String
,&str
)として扱えないので、バイト列(Vec<u8>
)として読み込む。つまり.read_to_string()
ではなく.read()
を使う。 - バイト列 → UTF-8 の変換には
encoding_rs
クレートを使う。 - 上記コード中
res
はCow<str>
型になるので、.into_owned()
でString
に変換する。
Cow
について
初めて見る型だったので公式ドキュメントを読んだ。
Enum std::borrow::Cow
pub enum Cow<'a, B>
where
B: 'a + ToOwned + ?Sized,
{
Borrowed(&'a B),
Owned(<B as ToOwned>::Owned),
}
A clone-on-write smart pointer.
「参照(&str
)と所有(String
)のどちらでも対応可能な型」とのこと。
.into_owned()
メソッドにより純粋な所有型(String
)に変換できる。
pub fn decode<'a>(
&'static self,
bytes: &'a [u8]
) -> (Cow<'a, str>, &'static Encoding, bool)
Decode complete input to Cow<'a, str> with BOM sniffing.
そしてencoding_rs
の.decode()
の返り値はCow
を含むタプル型である。
パターンマッチで必要な要素のみを取り出してから.into_owned()
で変換すれば、UTF-8のString
が得られる。
単純な文字コード変換で使う分には、Option
型やResult
型の返り値を.unwrap()
で処理するのと同じようなものと思えば良さそう。
参考
Rustプログラミング入門(オーム社)
https://www.ohmsha.co.jp/book/9784274224355/
Stack Overflow - How do I use the SHIFT-JIS encoding in Rust?
https://stackoverflow.com/questions/48136939/how-do-i-use-the-shift-jis-encoding-in-rust
docs encoding_rs
https://docs.rs/encoding_rs/0.8.23/encoding_rs/index.html
docs std::borrow::Cow into_owned()
https://doc.rust-lang.org/std/borrow/enum.Cow.html#examples-4
Pythonでやる場合の例
https://dev.classmethod.jp/articles/python-encoding/