Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/cmake/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++11 将大数据文件嵌入可执行二进制文件_C++11_Cmake_Initialization_Clion_Compile Time - Fatal编程技术网

C++11 将大数据文件嵌入可执行二进制文件

C++11 将大数据文件嵌入可执行二进制文件,c++11,cmake,initialization,clion,compile-time,C++11,Cmake,Initialization,Clion,Compile Time,我正在开发一个C++11应用程序,它应该作为一个可执行的二进制文件发布。或者,用户可以提供自己的CSV数据文件供应用程序使用。为了简化操作,假设每个元素的格式为key,value\n。我创建了一个结构,例如: typedef struct Data { std::string key; std::string value; Data(std::string key, std::string value) : key(key), value(value) {} } Dat

我正在开发一个C++11应用程序,它应该作为一个可执行的二进制文件发布。或者,用户可以提供自己的CSV数据文件供应用程序使用。为了简化操作,假设每个元素的格式为
key,value\n
。我创建了一个结构,例如:

typedef struct Data {
    std::string key;
    std::string value;

    Data(std::string key, std::string value) : key(key), value(value) {}
} Data;
默认情况下,应用程序应使用在单个头文件中定义的数据。我制作了一个简单的Python脚本来解析默认CSV文件,并将其放入头文件,如:

#ifndef MYPROJECT_DEFAULTDATA
#define MYPROJECT_DEFAULTDATA

#include "../database/DefaultData.h"

namespace defaults {
    std::vector<Data> default_data = {
        Data("SomeKeyA","SomeValueA"),
        Data("SomeKeyB","SomeValueB"),
        Data("SomeKeyC","SomeValueC"),

        /* and on, and on, and on... */

        Data("SomeKeyASFHOIEGEWG","SomeValueASFHOIEGEWG")
    }
}

#endif //MYPROJECT_DEFAULTDATA
\ifndef MYPROJECT\u DEFAULTDATA
#定义MYPROJECT\u DEFAULTDATA
#包括“./database/DefaultData.h”
命名空间默认值{
std::向量默认值_数据={
数据(“SomeKeyA”、“SomeValueA”),
数据(“SomeKeyB”、“SomeValueB”),
数据(“SomeKeyC”、“SomeValueC”),
/*不停地,不停地,不停地*/
数据(“SomeKeyASFHOIEGEWG”、“SomeValueASFHOIEGEWG”)
}
}
#endif//MYPROJECT\u DEFAULTDATA
唯一的问题是,这个文件很大。我说的是116'087(12M)行,将来可能会被更大的文件取代。当我包含它时,我的IDE试图解析它并更新索引。它把一切都拖慢了,以至于我几乎什么都写不出来

我正在寻找一种方法:

  • 阻止我的IDE(CLion)解析它或
  • 在cmake中创建一个开关,该开关将仅在发布可执行文件或
  • 以某种方式将数据直接注入可执行文件

  • 因为您的构建过程已经包含了一个预处理,它从CSV生成C++代码,这应该很容易。 步骤1:将大部分生成的数据放在.cpp文件中,而不是放在头文件中

    步骤2:生成代码,使其不使用
    向量
    字符串

    以下是如何做到这些:

    struct Data
    {
        string_view key;
        string_view value;
    };
    
    您将需要一个或类似类型的实现。虽然它是在C++17中标准化的,但它不依赖C++17特性

    至于数据结构本身,这是在标头中生成的内容:

    namespace defaults {
        extern const std::array<Data, {{GENERATED_ARRAY_COUNT}}> default_data;
    }
    
    命名空间默认值{
    extern const std::数组默认\u数据;
    }
    
    {{GENERATED_ARRAY_COUNT}}是数组中的项数。这就是生成的头应该公开的所有内容。生成的.cpp文件稍微复杂一些:

    static const char ptr[] =
        "SomeKeyA" "SomeValueA"
        "SomeKeyB" "SomeValueB"
        "SomeKeyC" "SomeValueC"
        ...
        "SomeKeyASFHOIEGEWG" "SomeValueASFHOIEGEWG"
    ;
    
    namespace defaults 
    {
      const std::array<Data, {{GENERATED_ARRAY_COUNT}}> default_data =
      {
          {{ptr+{{GENERATED_OFFSET}}, {{GENERATED_SIZE}}}, {ptr+{{GENERATED_OFFSET}}, {{GENERATED_SIZE}}}},
          {{ptr+{{GENERATED_OFFSET}}, {{GENERATED_SIZE}}}, {ptr+{{GENERATED_OFFSET}}, {{GENERATED_SIZE}}}},
          ...
          {{ptr+{{GENERATED_OFFSET}}, {{GENERATED_SIZE}}}, {ptr+{{GENERATED_OFFSET}}, {{GENERATED_SIZE}}}},
      };
    }
    
    static const char ptr[]=
    “SomeKeyA”“SomeValueA”
    “SomeKeyB”“SomeValueB”
    “SomeKeyC”“SomeValueC”
    ...
    “SomeKeyASFHOIEGEWG”“SomeValueASFHOIEGEWG”
    ;
    命名空间默认值
    {
    const std::数组默认\u数据=
    {
    {{ptr+{{GENERATED_OFFSET}}、{{GENERATED_SIZE}}}、{ptr+{{GENERATED_OFFSET}}、{{GENERATED_SIZE}}}},
    {{ptr+{{GENERATED_OFFSET}}、{{GENERATED_SIZE}}}、{ptr+{{GENERATED_OFFSET}}、{{GENERATED_SIZE}}}},
    ...
    {{ptr+{{GENERATED_OFFSET}}、{{GENERATED_SIZE}}}、{ptr+{{GENERATED_OFFSET}}、{{GENERATED_SIZE}}}},
    };
    }
    
    ptr
    是一个字符串,它是所有单个字符串的串联。不需要在单个字符串之间放置空格或
    \0
    字符或任何内容。但是,如果确实需要将这些字符串传递给以NULL结尾的字符串的API,则必须将它们复制到std::string中,或者让生成器在每个生成的子字符串后插入
    \0
    字符

    关键是
    ptr
    应该是一个巨大的字符数据块

    {{GENERATED_OFFSET}}和{{GENERATED_SIZE}}是表示单个子字符串的巨大字符数据块中的偏移量和大小


    这个方法可以解决你的两个问题。它在加载时会更快,因为它执行零动态分配。它将生成的字符串放入.cpp文件中,从而使您的IDE配合。

    并且您不能将实际的“默认值”CSV文件与可执行文件一起发送,因此在没有加载其他数据文件的情况下可以读取它?那么,创建一个包含文件实际内容的长字符串,像矢量一样包含该字符串,并在启动时解析该字符串如何?因此,您希望为用户提供一个可执行文件,但需要为每个用户执行不同的构建以合并其数据?(在他们给你数据文件之后)?你到底想解决什么问题?通常,在数据文件/数据库中存储数据(出于某种原因)与“性能”有关,启动时间是否如此重要?还是更重要的是,一旦启动,它就会“执行”?该计划多久启动一次?一天几次?一天一次?一周一次?一旦启动,它将运行多长时间?几分钟?小时?天?我这么问是因为我知道如何将文件“嵌入”到可执行文件中的任何其他方法都依赖于存储原始的未经分析的数据。也许您生成的数据源文件应该在外部构建到一个单独的库中,并且IDE不会真正触及它?使用and命令管理外部“库”(相对而言)比较容易。您实际上不需要库,只需要添加到主构建中的对象文件。只要您不打开自动生成的源文件,并将其放在从CLion中排除的单独目录中,您就不会有问题。@Someprogrammerdude:我没有说
    vector
    会分配多次。该
    vector
    中的每个
    std::string
    都可能有自己的分配,具体取决于字符串的大小以及该
    std::string
    实现上是否存在SSO。此外,还有一个事实,即每个
    字符串
    构造也将从字符串文本中复制出来。