为什么没有从 UTF8 编码数组创建字符串的专用方法?
我需要String从字节数组(不是Vec)构造。这有效:
let buf2 = [30, 40, 50];
let string2 = std::str::from_utf8(&buf2).unwrap().to_string();
- 为什么没有专门的数组/切片方法
String? - 为什么
from_utf8不是泛型的参数? - 上面的片段是惯用的 Rust 吗?
我最终不需要String和&str,但问题仍然存在。
回答
有两种from_utf8方法。一个从&[u8]到str,另一个从Vec<u8>? String. 为什么是两个?有什么不同?为什么没有一个可以直接从&[u8]到String?
便宜的转换
让我们查阅官方 Rust 文档。
str::from_utf8(v: &[u8]) -> Result<&str, Utf8Error>字符串切片(
&str)由字节(u8)组成,字节切片(&[u8])由字节组成,因此该函数在两者之间进行转换。并非所有字节切片都是有效的字符串切片,但是:&str要求它是有效的 UTF-8。from_utf8()检查以确保字节是有效的 UTF-8,然后进行转换。来源
如果&[u8]字节切片包含有效的 UTF-8 数据,&str则可以通过简单地将字节用作字符串数据来创建字符串切片。这是一个非常便宜的操作,不需要分配。
String::from_utf8(vec: Vec<u8>) -> Result<String, FromUtf8Error>将字节向量转换为
String. ...为了效率,此方法将注意不要复制向量。来源
同样的事情也适用String的方法。AString是一种拥有类型:它需要拥有底层字节,而不仅仅是指向其他人的字节。如果它需要一个&[u8]它就必须分配内存。但是,如果您已经拥有一个,Vec<u8>那么从Vec<u8>to转换String是一个便宜的操作。String可以使用并重Vec<u8>用其现有的堆缓冲区。无需分配。
显式堆分配和复制
Rust 希望你注意内存分配和复制。只提供廉价的转换方法。任何分配或复制都需要额外的方法调用。它很优雅。快路径方便,慢路径麻烦。您要么需要:
- 将您的转换
&[u8]为&str(便宜的),然后将其转换为拥有的String(昂贵的);或者 - 将您转换
&[u8]为拥有的Vec<u8>(昂贵的),然后将其转换为String(便宜的)。
无论哪种方式,这是您的选择,它需要第二个方法调用。