str :: as_bytes和CString :: as_bytes_with_nul之间有区别吗?

时间:2019-02-09 17:53:18

标签: string rust

这样做之间有什么区别吗?

name.as_bytes()

这:

CString::new(name)?.as_bytes_with_nul()

我想从name(即String)中获取字节,以便可以轻松地通过网络发送它们,而且我不确定CString是否是偶数在这里是必需的。

2 个答案:

答案 0 :(得分:5)

as_bytes_with_nul的文档始于:

  

等效于as_bytes函数,除了返回的切片包含结尾的nul终止符。

as_bytes是:

  

返回的切片包含结尾的nul终止符

(在原始报价中强调)

由您决定是否需要传输nul字节,这取决于您如何通过网络发送数据(TCP / UDP?如何通过TCP传输原始二进制数据?如果这样,您打算如何分隔消息? JSON等)。

答案 1 :(得分:1)

只要您的字符串中没有0 UTF-8代码单元,name.as_bytes()CString::new(name)?.as_bytes()应该为您提供完全相同的字节。此外,CString的{​​{1}}将仅附加一个.as_bytes_with_null()字节。这是一个带有相当复杂的UTF-8字符串的小演示:

0

结果符合预期(您可能会认识到use std::ffi::CString; fn main() { let message: String = "\nßщ\u{1F601}".to_string(); println!("bytes_1: {:?}", message.as_bytes()); println!("bytes_2: {:?}", CString::new(message.clone()).unwrap().as_bytes()); println!("bytes_3: {:?}", CString::new(message.clone()).unwrap().as_bytes_with_nul()); } ,它对应于ASCII字符10,在utf-8中以相同的方式编码):

\n

如果您的字符串中包含U+0000which is a valid Unicode code point,并由bytes_1: [10, 195, 159, 209, 137, 240, 159, 152, 129] bytes_2: [10, 195, 159, 209, 137, 240, 159, 152, 129] bytes_3: [10, 195, 159, 209, 137, 240, 159, 152, 129, 0] 中的单个0字节编码,并且会出现在普通字符串中,则会出现问题。例如:

UTF-8

会给你

use std::ffi::CString;

fn main() {
    let message: String = "\n\u{0000}\n\u{0000}".to_string();
    println!("bytes_1: {:?}", message.as_bytes());
    println!(
        "bytes_2: {:?}",
        match CString::new(message.clone()) {
            Err(e) => format!("an error: {:?}, as expected", e),
            Ok(_) => panic!("won't happen. .as_bytes() must fail."),
        }
    );
}

因此,简单的bytes_1: [10, 0, 10, 0] bytes_2: "an error: NulError(1, [10, 0, 10, 0]), as expected" 版本成功了,但是.as_bytes()版本却失败了。我建议尽可能使用CString和UTF-8,没有理由先将其转换为CString。