RustでStringとVec<u8>を相互に変換
Rustにおいて、文字列String
はUTF-8として有効なバイトのベクタVec<u8>
である。String
とVec<u8>
を相互に変換するにはinto_bytes
やString::from_utf8
を使う。
&str
と&[u8]
の相互変換については以下の記事を参照。
- 関連記事: Rustで&strと&[u8]を相互に変換
以下のサンプルコードでは、説明のため、型推論によって省略できるときも明示的に型注釈を記述している場合がある。また、簡単のためunwrap
を使っている。必要であればその他のメソッドやmatch
などで処理すればよい。
StringをVec<u8>に変換: into_bytes
String
をVec<u8>
に変換するにはinto_bytes
を使う。
let s: String = String::from("abc😀");
let v: Vec<u8> = s.into_bytes();
assert_eq!(v, [97, 98, 99, 240, 159, 152, 128]);
他のinto_***
という名前のメソッドと同じく、into_bytes
の引数はself
。所有権が移動し、元のString
は使えなくなるので注意。
なお、as_bytes
というメソッドもあり、こちらはバイトのスライス&[u8]
を返す。
let s: String = String::from("abc😀");
let b: &[u8] = s.as_bytes();
assert_eq!(b, [97, 98, 99, 240, 159, 152, 128]);
他のas_***
という名前のメソッドと同じく、as_bytes
の引数は&self
。所有権は移動しない。
Vec<u8>をStringに変換: String::from_utf8, String::from_utf8_lossy
String::from_utf8
Vec<u8>
をString
に変換するにはString::from_utf8
を使う。
String
はUTF-8として有効であることが保証されている(=有効でなければいけない)。したがって、UTF-8として有効なVec<u8>
はString
に変換できるが、有効でない場合は変換できない。
from_utf8
の返り値の型はResult
。UTF-8として有効でないベクタに対してはエラーを返す。
let v: Vec<u8> = vec![97, 98, 99, 240, 159, 152, 128];
let s: String = String::from_utf8(v).unwrap();
assert_eq!(s, "abc😀");
let v: Vec<u8> = vec![97, 98, 99, 255];
let is_err: bool = String::from_utf8(v).is_err();
assert!(is_err);
unsafe
な関数として、UTF-8として有効かどうかのチェックを行わないString::from_utf8_unchecked
も提供されている。UTF-8として有効であることが確実で、チェックのためのオーバーヘッドを避けたい場合に使う。
let v: Vec<u8> = vec![97, 98, 99, 240, 159, 152, 128];
let s: String = unsafe { String::from_utf8_unchecked(v) };
assert_eq!(s, "abc😀");
from_utf8
とfrom_utf8_unchecked
の引数の型はVec<u8, Global>
。参照ではなく、所有権が移動するので注意。
なお、std::str::from_utf8
を使うとVec<u8>
を&str
に変換することも可能。
let v: Vec<u8> = vec![97, 98, 99, 240, 159, 152, 128];
let s: &str = std::str::from_utf8(&v).unwrap();
assert_eq!(s, "abc😀");
詳細は以下の記事を参照。
- 関連記事: Rustで&strと&[u8]を相互に変換
String::from_utf8_lossy
String::from_utf8_lossy
を使うと、UTF-8として有効でない部分を「�(U+FFFD
)」に置き換えて変換できる。有効な場合はそのまま。
let v: Vec<u8> = vec![97, 98, 99, 240, 159, 152, 128];
let s: String = String::from_utf8_lossy(&v).into_owned();
assert_eq!(s, "abc😀");
let v: Vec<u8> = vec![97, 98, 99, 255];
let s: String = String::from_utf8_lossy(&v).into_owned();
assert_eq!(s, "abc�");
from_utf8_lossy
の引数の型は&[u8]
。配列とベクタの参照(&[u8; N]
, &Vec<u8>
)も渡せる。参照なので所有権は移動しない。
let b: [u8; 4] = [97, 98, 99, 255];
let s: String = String::from_utf8_lossy(&b).into_owned();
assert_eq!(s, "abc�");
from_utf8_lossy
の返り値の型はCow<'_, str>
。
This function returns a
Cow<'a, str>
. If our byte slice is invalid UTF-8, then we need to insert the replacement characters, which will change the size of the string, and hence, require aString
. But if it’s already valid UTF-8, we don’t need a new allocation. This return type allows us to handle both cases. String::from_utf8_lossy in std::string - Rust
上の例ではinto_owned
でString
に変換しているが、参照が必要な場合はそのまま&
を付けて渡せばよい。
let mut s = String::from("xyz_");
let b: [u8; 4] = [97, 98, 99, 255];
let cow = String::from_utf8_lossy(&b);
s.push_str(&cow);
assert_eq!(s, "xyz_abc�");