Rust:将&str保存为字节然后将其转换回来的惯用方法

qnakjoqk  于 2022-11-12  发布在  其他
关注(0)|答案(2)|浏览(108)

我想将一个文件名(最多32字节)保存在一个字节数组中,然后将字节转换回String。由于存在一系列文件名,因此底层数组被设计为固定大小(即32字节)。

// name is the file name `&str`
let mut arr = [0u8; 32];
arr[..name.len()].copy_from_slice(name.as_bytes());

但问题是:有可能获得文件名32字节长数组(arr),而不存储长度?
在C/C++中,由于原始字符串以0结尾,因此提供了许多内置函数:

// store
memcpy(arr, name.c_str(), name.length() + 1);
// convert it back
char *raw_name = reinterpret_cast<char*>(arr);

那么,在Rust中,什么是惯用的方法呢?一种可能的方法是使用额外的5位显式存储大小,但似乎这不是最好的方法。

lmvvr0a8

lmvvr0a81#

我不知道reinterpret_cast<char*>在C语言中的具体作用,但我认为您可以用std::str::from_utf8做类似的事情

let name ="hello";
    let mut arr = [0u8; 32];
    arr[..name.len()].copy_from_slice(name.as_bytes());
    println!("{:?}",arr);
    //[104, 101, 108, 108, 111, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
    let recoverd_str = std::str::from_utf8(arr.as_slice()).unwrap();
    println!("{:?}",recoverd_str);
    //"hello\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
    println!("{}",recoverd_str);
    //hello

但是,recovered_strname实际上并不相同...但是您可以修剪尾随的空字节!检查此answer

7y4bm7vi

7y4bm7vi2#

另一种将以空值结束的[0u8; 32]转换为&str的方法是通过CStr,使用不稳定的from_bytes_until_nul


# ![feature(cstr_from_bytes_until_nul)]

CStr::from_bytes_until_nul(arr.as_slice()).unwrap().to_str().unwrap()

Playground
然而,这要求切片中包含一个0字节,可存储的最大字符串长度变为31字节。(尝试在操场上将数组长度减少到5,看看32字节长的字符串会发生什么。)
如果你想存储32字节的字符串,你可以使用std::str::from_utf8(arr.split(|&c| c == 0).next().unwrap()).unwrap(),但是我不认为这是惯用的......

相关问题