首页 > 解决方案 > 多次运行读取 csv 文件的 c++ 脚本

问题描述

我有一个要运行多次的 c++ 控制台应用程序。它每次运行时都会读取一个不会更改的大型 csv 文件。这是一个缓慢的过程。有什么方法可以将文件“加载”到内存中,而不必每次运行文件时都读取。

我在想 R 和 python 的工作方式。您将 csv 作为数据框加载,并且可以在其他 R 脚本中使用它,而无需每次都加载。

标签: pythonc++r

解决方案


每次您的 C++ 应用程序退出时,它的内存都会被释放,这意味着您的数据将不会被保留下次使用。因此,如果您将数据存储在应用程序内存堆中,则应在每次运行应用程序时从文件中读取数据。

如果你真的想避免从文件系统读取数据,最简单的方法是使用单独的进程,即内存数据库,例如 Redis 或 SQLite,这样你就可以读取一次 cdv,将其存储在 DB 内存中,然后通过您的 C++ 应用程序访问您的数据。

内存数据库列表

在您的情况下,我建议选择Redis(比 SQLite 更容易,因为您不需要创建表)。

如果你不熟悉它,上手很简单:Redis 是一个键值存储系统。您只需要为我们的环境安装一个redis服务器,您就可以使用一个C++库来立即在其中存储和检索数据。您所要做的就是使用两种类型的命令:SET(当您第一次读取 CSV 文件时)和GET(当您访问数据以进行处理时)。

存储数据的最简单方法可能是使用由文件名和行号组成的密钥来存储 CSV 的每一行。例如,如果您的文件名为Artists_rock.csv,您可以这样做来存储第 909 行:

SET ART_ROCK_909 "Lennon;John;Liverpool"

你可以这样得到你的记录:

GET ART_ROCK_909

密钥格式由您决定,这样就可以轻松地迭代或直接访问一行,就像您正在阅读文件一样。

如果您使用 C++ 库来解析您的 CSV 记录(这意味着您永远不会操纵原始字符串),您还可以将您的对象存储为一个集合并使用HSETHGET对其进行操作。前面的示例如下所示:

HSET ART_ROCK_909 name "Lennon" fistname "John" birthplace "Liverpool"

你会用

HGET ART_ROCK_909 birthplace

您需要做的就是选择一个 C++ 库来与您的 Redis 服务器通信。hiredis C 库有许多包装器,例如您可以在 Github 上找到的 redis-plus-plus。

这是一个入门示例代码。为了保持与上面相同的示例,相应的代码如下所示:

  #include <sw/redis++/redis++.h>
    
    using namespace sw::redis;
    
    try {
        // Create an Redis object, which is movable but NOT copyable.
        auto redis = Redis("tcp://127.0.0.1:6379");
    
        auto line = my_csv_reading_function();
    
        redis.set("ART_ROCK_909", line);
        auto val = redis.get("ART_ROCK_909");    // val is of type OptionalString. See 'API Reference' section for details.
    }

推荐阅读