如何在不知道编译时结构的情况下读取CSV数据?

如何解决如何在不知道编译时结构的情况下读取CSV数据?

我对Rust还是很陌生,并试图实现某种数据库。用户应通过提供一个表名,一个列名向量和一个列类型向量(通过枚举实现)来创建表。填写表格应通过指定csv文件来完成。但是,这要求在编译时指定表行的结构,如基本示例所示:

#[derive(Debug,Deserialize,Eq,PartialEq)]
struct Row {
    key: u32,name: String,comment: String
}
use std::error::Error;
use csv::ReaderBuilder;
use serde::Deserialize;
use std::fs;

fn read_from_file(path: &str) -> Result<(),Box<dyn Error>> {
    let data = fs::read_to_string(path).expect("Unable to read file");
    let mut rdr = ReaderBuilder::new()
        .has_headers(false)
        .delimiter(b'|')
        .from_reader(data.as_bytes());
    let mut iter = rdr.deserialize();

    if let Some(result) = iter.next() {
        let record:Row = result?;
        println!("{:?}",record);
        Ok(())
    } else {
        Err(From::from("expected at least one record but got none"))
    }   
}

是否可以使用通用表信息代替“行”结构来进行反序列化的结果转换?是否可以根据列类型的组合大小简单地分配内存并解析其中的记录?我会在C中做这样的事情...

解决方法

是否可以使用通用表信息代替“行”结构来进行反序列化的结果转换?

在编译时将所有泛型替换为具体类型。如果您不知道运行时所需的类型,则不需要“泛型”。

是否可以根据列类型的组合大小简单地分配内存并解析其中的记录?我会在C中做这样的事情...

我建议改用Box<dyn Any>,以便能够存储任何类型的引用,并且仍然知道它是什么类型。

此方法的维护成本非常高。您必须在要使用单元格值的任何地方管理每种可能的值类型。另一方面,您不需要每次都解析值,只需在运行时进行一些类型检查即可。

我已经使用std::any::TypeId来标识类型,但是不能在match表达式中使用它。您可以考虑使用自定义枚举作为类型标识符。

use std::any::{Any,TypeId};
use std::io::Read;

use csv::Reader;

#[derive(Default)]
struct Table {
    name: String,headers: Vec<(String,TypeId)>,data: Vec<Vec<Box<dyn Any>>>,}

impl Table {
    fn add_header(&mut self,header: String,_type: TypeId) {
        self.headers.push((header,_type));
    }

    fn populate_data<R: Read>(
        &mut self,rdr: &mut Reader<R>,) -> Result<(),Box<dyn std::error::Error>> {
        for record in rdr.records() {
            let record = record?;
            let mut row: Vec<Box<dyn Any>> = vec![];
            for (&(_,type_id),value) in self.headers.iter().zip(record.iter()) {
                if type_id == TypeId::of::<u32>() {
                    row.push(Box::new(value.parse::<u32>()?));
                } else if type_id == TypeId::of::<String>() {
                    row.push(Box::new(value.to_owned()));
                }
            }
            self.data.push(row);
        }
        Ok(())
    }
}

impl std::fmt::Display for Table {
    fn fmt(&self,f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        writeln!(f,"Table: {}",self.name)?;
        for (name,_) in self.headers.iter() {
            write!(f,"{},",name)?;
        }
        writeln!(f)?;
        for row in self.data.iter() {
            for cell in row.iter() {
                if let Some(&value) = cell.downcast_ref::<u32>() {
                    write!(f,value)?;
                } else if let Some(value) = cell.downcast_ref::<String>() {
                    write!(f,value)?;
                }
            }
            writeln!(f)?;
        }
        Ok(())
    }
}

fn main() {
    let mut table: Table = Default::default();
    table.name = "Foo".to_owned();
    table.add_header("key".to_owned(),TypeId::of::<u32>());
    table.add_header("name".to_owned(),TypeId::of::<String>());
    table.add_header("comment".to_owned(),TypeId::of::<String>());
    let data = "\
key,name,comment
1,foo,foo comment
2,bar,bar comment
";
    let mut rdr = Reader::from_reader(data.as_bytes());
    table.populate_data(&mut rdr).unwrap();
    print!("{}",table);
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-