You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Rust加载格式不规则的CSV文件?

解决CSV文件格式不一致导致的加载错误

需要加载的test.csv文件前两行是元数据(包含年份、学期等信息),格式为5个字段(含末尾空字段),但第三行及之后的数据行仅4个字段,这种格式差异导致csv库抛出UnequalLengths错误。

test.csv内容

[YEAR],2022,[Q],1,
[TEST],mid-term,[GRADE],3,
FirstName,LastName,Score,
AA,aaa,97,
BB,bbbb,15,
CC,cccc,66,
DD,ddd,73,
EE,eeeee,42,
FF,fffff,52,
GG,ggg,64,
HH,h,86,
II,iii,88,
JJ,jjjj,72,

错误信息

StringRecord(["[YEAR]", "2022", "[Q]", "1", ""])
StringRecord(["[TEST]", "mid-term", "[GRADE]", "3", ""])
Error: Error(UnequalLengths { pos: Some(Position { byte: 47, line: 2, record: 2 }), expected_len: 5, len: 4 })
error: process didn't exit successfully: `target\debug\read_csv.exe` (exit code: 1)

当前代码(main.rs)

use csv::Error;
use csv::ReaderBuilder;
use encoding_rs;
use std::fs;

fn main() -> Result<(), Error> {
    let path = "./test.csv";
    let file = fs::read(path).unwrap();
    let (res, _, _) = encoding_rs::SHIFT_JIS.decode(&file);

    let mut reader = ReaderBuilder::new()
        .has_headers(false)
        .from_reader(res.as_bytes());

    for result in reader.records() {
        let record = result?;
        println!("{:?}", record)
    }

    Ok(())
}

版本信息

cargo = "1.62.0"
rustc = "1.62.0"
csv = "1.1.6"
encoding_rs = "0.8.31"

解决方案

有两种处理方式,可根据实际需求选择:

方式1:分开处理元数据与数据行

如果只需要读取第三行及之后的业务数据,或者需要单独解析前两行元数据,可以先手动读取并处理前两行,再读取剩余数据行:

use csv::Error;
use csv::ReaderBuilder;
use encoding_rs;
use std::fs;

fn main() -> Result<(), Error> {
    let path = "./test.csv";
    let file = fs::read(path).unwrap();
    let (res, _, _) = encoding_rs::SHIFT_JIS.decode(&file);

    let mut reader = ReaderBuilder::new()
        .has_headers(false)
        .from_reader(res.as_bytes());

    // 读取并处理前两行元数据
    if let Ok(record) = reader.records().next().unwrap() {
        println!("元数据1: {:?}", record);
    }
    if let Ok(record) = reader.records().next().unwrap() {
        println!("元数据2: {:?}", record);
    }

    // 读取剩余业务数据行
    for result in reader.records() {
        let record = result?;
        println!("数据行: {:?}", record)
    }

    Ok(())
}

方式2:允许不等长记录

如果需要完整读取所有行,且不想因为字段长度不一致触发报错,可以通过flexible(true)配置csv阅读器,关闭行字段长度一致性检查:

use csv::Error;
use csv::ReaderBuilder;
use encoding_rs;
use std::fs;

fn main() -> Result<(), Error> {
    let path = "./test.csv";
    let file = fs::read(path).unwrap();
    let (res, _, _) = encoding_rs::SHIFT_JIS.decode(&file);

    let mut reader = ReaderBuilder::new()
        .has_headers(false)
        .flexible(true) // 允许字段长度不一致的记录
        .from_reader(res.as_bytes());

    for result in reader.records() {
        let record = result?;
        println!("{:?}", record)
    }

    Ok(())
}

补充说明

  • flexible(true)适用于格式不规则但需要完整读取的场景,会跳过csv库对行字段长度的校验。
  • 如果需要将第三行作为数据表头,可调整has_headers配置为true,结合headers()方法获取表头后再读取数据。

内容的提问来源于stack exchange,提问作者Notebook

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 20:54:16