LoginSignup
8
6

More than 3 years have passed since last update.

[Rust] Shift_JISをUTF-8に変換する

Last updated at Posted at 2020-06-20

試作品

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クレートを使う。
  • 上記コード中resCow<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/

8
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
6