如何将十六进制字符串转换为u8切片?

27

我有一个这样的字符串 "090A0B0C",我想要将它转换成类似于 [9, 10, 11, 12] 的切片。最好的方法是什么?

我不想将单个十六进制字符元组转换为单个整数值。我想将由多个十六进制字符元组组成的字符串转换为多个整数值的切片。


4
  1. 我们希望你能自己努力解决问题。
  2. 我认为你不会想获得一个“切片”,因为那个不会拥有内容。
- E net4
可能是将十六进制字符串转换为十进制整数的重复问题。 - Stargateur
@Stargateur,与我的问题重叠的部分是在我提问之后编辑的。 - Philippe
2个回答

44

如果你想避免依赖于hex创建,你也可以自己实现十六进制编码和解码:

use std::{fmt::Write, num::ParseIntError};

pub fn decode_hex(s: &str) -> Result<Vec<u8>, ParseIntError> {
    (0..s.len())
        .step_by(2)
        .map(|i| u8::from_str_radix(&s[i..i + 2], 16))
        .collect()
}

pub fn encode_hex(bytes: &[u8]) -> String {
    let mut s = String::with_capacity(bytes.len() * 2);
    for &b in bytes {
        write!(&mut s, "{:02x}", b).unwrap();
    }
    s
}

请注意,如果字符串长度为奇数,则decode_hex()函数会出现错误。我已经在playground上提供了一个具有更好的错误处理和优化编码器的版本

2
@Miere 这个答案的主要目的是提供两个简单的函数,如果您不想出于某些原因使用 hex crate,例如为了减少编译时间,这些函数可以使用。我不太清楚为什么我在 playground 上写了版本。我的实现是否比 hex crate 有任何优势?如果有的话,我很乐意将其放入一个新的 crate 中。 - Sven Marnach
我会对其进行基准测试。一旦我得到结果,我会回到你这里,@SvenMarnach。 - Miere
encode_hex有一个未处理的来自write!宏的Result - Herohtar
1
@Herohtar 向字符串写入总是返回 Ok(())。我添加了 .unwrap() 以明确表示这一点。 - Sven Marnach
如果我早知道使用step_by方法,就能省去很多麻烦了!谢谢! - Brian Kung
显示剩余5条评论

35

你可以使用hex crate实现。 decode函数看起来就是你想要的:

fn main() {
    let input = "090A0B0C";

    let decoded = hex::decode(input).expect("Decoding failed");

    println!("{:?}", decoded);
}
以上内容将打印出[9, 10, 11, 12]。请注意,decode返回一个分配在堆上的Vec<u8>,如果您想解码成数组,则需要使用decode_to_slice函数。
fn main() {
    let input = "090A0B0C";

    let mut decoded = [0; 4];
    hex::decode_to_slice(input, &mut decoded).expect("Decoding failed");

    println!("{:?}", decoded);
}

或者使用FromHex特性:

use hex::FromHex;

fn main() {
    let input = "090A0B0C";

    let decoded = <[u8; 4]>::from_hex(input).expect("Decoding failed");

    println!("{:?}", decoded);
}

谢谢您的回答,我已经修复了实现中的一个错误。 - Corfucinas
1
如果可以的话,我会再给你一个赞。我一直在尝试做这件事,却没有意识到我已经有了 hex 包。我之前看到了你的答案,今天又帮了我一次忙! - Nico Serrano

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接