Rust中如何移除或替换文件中的非UTF-8字符?
解决方法
首先明确你要处理的字节序列:你提到的二进制串11101111 10111101 10111101对应十六进制的0xEF 0xBD 0xBD,这是UTF-8标准里的替换字符�;而目标字符£的UTF-8编码是0xC2 0xA3。
由于文件仅5KB,直接在内存中处理Vec<u8>是最高效的方式,以下是具体实现:
1. 手动实现序列替换(无额外依赖)
写一个简单的函数遍历字节数组,替换所有匹配的目标序列:
fn replace_byte_sequence(data: &[u8], target: &[u8], replacement: &[u8]) -> Vec<u8> { let mut result = Vec::with_capacity(data.len()); let mut current_pos = 0; let target_len = target.len(); while current_pos <= data.len().saturating_sub(target_len) { if &data[current_pos..current_pos + target_len] == target { // 匹配到目标序列,替换 result.extend_from_slice(replacement); current_pos += target_len; } else { // 未匹配,保留当前字节 result.push(data[current_pos]); current_pos += 1; } } // 处理剩余未匹配的尾部字节 result.extend_from_slice(&data[current_pos..]); result }
2. 调用函数并处理CSV
把读取到的Vec<u8>传入函数,再用csv crate处理清理后的数据:
use std::io::Cursor; use csv::Reader; // 假设你已将文件内容读取到data: Vec<u8>中 let target_sequence = &[0xEF, 0xBD, 0xBD]; let pound_symbol = &[0xC2, 0xA3]; // £的UTF-8编码 let cleaned_data = replace_byte_sequence(&data, target_sequence, pound_symbol); // 将清理后的字节包装成Read对象,供csv读取 let mut reader = Reader::from_reader(Cursor::new(cleaned_data)); // 后续CSV解析逻辑示例 for result in reader.records() { let record = result.expect("Failed to read CSV record"); // 处理每一行数据 }
如果需要移除而非替换目标序列,只需把pound_symbol换成空切片&[]即可。
备选方案:使用第三方库简化代码
如果不介意引入依赖,可以用bytes crate的BytesMut来简化替换逻辑:
use bytes::BytesMut; let mut buf = BytesMut::from(&data[..]); let target = &[0xEF, 0xBD, 0xBD]; let replacement = &[0xC2, 0xA3]; while let Some(pos) = buf.windows(target.len()).position(|win| win == target) { buf.splice(pos..pos+target.len(), replacement.iter().cloned()); } let cleaned_data = buf.into_vec();
这种方式代码更简洁,但需要在Cargo.toml中添加bytes = "1.0"依赖。
内容的提问来源于stack exchange,提问作者maxweld
相关产品推荐
相关产品推荐

