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

使用Rust读取固定宽度文件并导入Polars DataFrame遇问题

问题分析与解决

核心问题

你的代码中,从文件读取的from_file方法缺少指定每行固定宽度的关键步骤——字符串版本的from_string调用了.width(72)来定义行长度,但文件读取逻辑遗漏了这一步。fixed_width的Reader从文件读取时必须明确每行宽度,否则无法确定行边界,导致程序卡住无响应。

修复后的代码

修改from_file方法,添加.width(72)(和字符串版本一致,你的文件每行长度为72):

use serde::{Serialize, Deserialize};
use fixed_width::{FixedWidth, FieldSet, Reader};


fn main() {
    let r_file = "path/to/file.r01";
    // let data = String::from("R   5001.00   1001.00                          513777.5 2093285.7   0.0
R   5001.00   1002.00                          513786.6 2093281.6   0.0
R   5001.00   1003.00                          513795.7 2093277.4   0.0
R   5001.00   1004.00                          513708.8 2093273.3   0.0
");

    #[derive(Serialize, Deserialize, Debug)]
    struct SpsRecord {
        pub line: f32,
        pub point: f32,
        pub easting: f32,
        pub northing: f32
    }

    impl FixedWidth for SpsRecord {
        fn fields() -> FieldSet {
            FieldSet::Seq(vec![
                FieldSet::new_field(1..11).name("line"),
                FieldSet::new_field(11..21).name("point"),
                FieldSet::new_field(46..55).name("easting"),
                FieldSet::new_field(55..65).name("northing")
            ])
        }
    }

    impl SpsRecord {
        fn from_file(path: &str) -> Result<Vec<Self>, fixed_width::Error> {
            // 添加.width(72)指定每行固定宽度
            let mut reader = Reader::from_file(path)?.width(72);
            let records: Result<Vec<Self>, fixed_width::Error> = reader
                .byte_reader()
                .filter_map(Result::ok)
                .map(|bytes| fixed_width::from_bytes(&bytes))
                .collect();
            records // 直接返回Result,无需额外match语句
        }

        // fn from_string(data: &str) -> Result<Vec<Self>, fixed_width::Error> {
        //     let mut reader = Reader::from_string(data).width(72);
        //     let records: Result<Vec<Self>, fixed_width::Error> = reader
        //         .byte_reader()
        //         .filter_map(Result::ok)
        //         .map(|bytes| fixed_width::from_bytes(&bytes))
        //         .collect();
        //     records
        // }
    }

    println!("Reading {}...", r_file);
    match SpsRecord::from_file(r_file) {
        Ok(records) => {
            for record in records {
                println!("{:?}", record);
            }
        }
        Err(err) => {
            eprintln!("{:#?}", err);
        }
    }

    // println!("Reading {}...", data);
    // match SpsRecord::from_string(&data) {
    //     Ok(records) => {
    //         for record in records {
    //             println!("{:?}", record);
    //         }
    //     }
    //     Err(err) => {
    //         eprintln!("{:#?}", err);
    //     }
    // } 
}

额外优化说明

  • 直接返回records变量即可,无需额外的match语句,Result类型本身符合方法返回要求。
  • 若运行仍报错,可通过eprintln!打印的错误信息排查文件路径是否正确。

转Polars DataFrame示例

解析完成后,可将Vec<SpsRecord>转换为Polars DataFrame:

use polars::prelude::*;

// 假设已获取records: Vec<SpsRecord>
let df = DataFrame::new(vec![
    Series::new("line", records.iter().map(|r| r.line).collect::<Vec<f32>>()),
    Series::new("point", records.iter().map(|r| r.point).collect::<Vec<f32>>()),
    Series::new("easting", records.iter().map(|r| r.easting).collect::<Vec<f32>>()),
    Series::new("northing", records.iter().map(|r| r.northing).collect::<Vec<f32>>()),
]).unwrap();

println!("{}", df);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 01:10:03