【问题标题】:Include CSV File in Complied Binary在编译后的二进制文件中包含 CSV 文件
【发布时间】:2019-08-17 02:10:10
【问题描述】:

我想将一个 CSV 文件编译到我的二进制文件中,这样当我运行我的 EXE 应用程序时,它就不需要文件夹中所需的 CSV 文件,并且 EXE 中已经有 CSV 文件数据。

例如,我有多个 CSV 文件,其中包含 2 列和 150 多行字符串,我希望在运行时将其解析为 C++ 映射。当我使用这个应用程序时,我不希望它在一个包含多个 CSV 文件的文件夹中,而只是一个更便携的 EXE。如果这些 CSV 文件中的数据必须更改,那么我只需使用更新的 CSV 文件重新构建解决方案。

C++ 能够做到这一点吗?如果是这样,我会怎么做?我不是在寻找我想要的设计方式的替代方案,我想让它列出我所描述的方式,如果不可能,我将在头文件中创建一个数组或枚举。

【问题讨论】:

  • 听起来您应该为输出.cpp 和/或.hpp 文件的.csv 文件创建一个编译器。当然,它可以用 C++ 或一个简单的脚本来完成。
  • 是的,一般来说是可能的。有几种方法。你用什么来构建你的程序?视觉工作室?制作?您在项目中使用 Qt 吗?
  • 我实际上不得不为 OpenGL 的着色器做这样的事情。执行此操作的最简单方法是将 CSV 值逐字存储到源代码中某处的字符串中,然后可以稍后在解析器中使用。现在一个更复杂和更灵活的解决方案将是@TedLyngmo 所说:创建一个 CVS 到 .cpp 和头文件,它会自动与您的预构建脚本一起运行 - cpp 将包含带有内容的大字符串,而标题是字符串的声明与内容,因此您可以将其包含在其他脚本中。
  • ... 如果您有不同格式的.csv 文件想要转换成不同的 C++ 类型,您可以创建一个文件来描述应该如何进行转换。 foo.csv 可能有一个 foo.csv2cpp,您的 .csv 编译器会读取它。在编译器中插入并将结果构建到构建依赖链中应该很容易。

标签: c++ csv


【解决方案1】:

我喜欢这里一些人的建议,并为“csv”到“c++ header”文件编译器创建了一个工作示例。

它甚至可以处理不同列大小的 CSV。

它将结果存储为std::string_view数组的compile-time-constexpr数组。

也许它可以给你基本的想法:

#include <iostream>
#include <string>
#include <array>
#include <vector>
#include <regex>
#include <sstream>
#include <fstream>
#include <algorithm>

// The delimiter
const std::regex re(",");

std::istringstream sourceCSV1{R"(A00,A01,A02
A10,A11,A12
A20,A21,A22)"};

std::istringstream sourceCSV2{R"(B00,B01
B10,B11,B12,B13,B14
B20,B21,B22,B23)"};


// Define Alias for Easier Reading
using Columns = std::vector<std::string>;
using CSV = std::vector<Columns>;


// Proxy for the input Iterator
struct ColumnProxy {    
    // Overload extractor. Read a complete line
    friend std::istream& operator>>(std::istream& is, ColumnProxy& cp) {

        // Read a line
        std::string line; cp.columns.clear();
        std::getline(is, line);

        // Split values and copy into resulting vector
        std::copy(std::sregex_token_iterator(line.begin(), line.end(), re, -1),
            std::sregex_token_iterator(),
            std::back_inserter(cp.columns));
        return is;
    }

    // Type cast operator overload.  Cast the type 'Columns' to std::vector<std::string>
    operator std::vector<std::string>() const { return columns; }
protected:
    // Temporary to hold the read vector
    Columns columns{};
};

void convertCSV2Hpp(std::istream& is, std::ostream& os, std::string& variableName)
{
   // Read complete CSV File
   CSV csvFile { std::istream_iterator<ColumnProxy>(is), std::istream_iterator<ColumnProxy>() };
   // Get maximumn number of columns in CSV file
   size_t maxCols = std::max_element(csvFile.begin(),csvFile.end(),[](const Columns& c1, const Columns& c2){ return c1.size() < c2.size();})->size();

   // Build output header file 
   std::string includeGuard(variableName);
   std::transform(variableName.begin(), variableName.end(),includeGuard.begin(), ::toupper);

   // Print header of file
   os << "#ifndef " << includeGuard << "_HPP" << "\n#define " << includeGuard << "_HPP\n\n#include <string>\n#include <array>\n\n" 
       << "constexpr size_t " << variableName << "NumberOfRows {" << csvFile.size() << "U};\n"
       << "constexpr size_t " << variableName << "NumberOfColumns {" << maxCols << "U};\n\n"
       << "constexpr std::array<std::array<std::string_view," << variableName << "NumberOfColumns" << ">," << variableName << "NumberOfRows" << "> " << variableName << " {{";

    // Print data
    for (size_t row = 0U; row < csvFile.size(); ++row) {
        os << "\n{";
        for (size_t col=0U; col<maxCols; ++col) {
            os << "\"" << ((col < csvFile[row].size())?csvFile[row][col]:"") << "\"" << ((col==maxCols-1)?"":", "); 
        }
        os <<  "},";
    }
    os << "\n}};\n\n#endif\n\n";
}

int main()
{
    std::string name("csv1");
    convertCSV2Hpp(sourceCSV1,std::cout,name);
    name = "csv2";
    convertCSV2Hpp(sourceCSV2,std::cout,name);
    return 0;
}

因为我在 SO 上没有文件,所以我使用 std::istringstream 作为输入,使用 std::cout 作为输出文件。你当然可以使用你喜欢的任何文件(流)。

【讨论】:

  • 您好,感谢大家为帮助我解决这个问题所付出的所有努力!我还不能实现它,但很高兴尝试一下!
猜你喜欢
  • 1970-01-01
  • 2010-12-23
  • 2015-01-31
  • 1970-01-01
  • 1970-01-01
  • 2018-05-17
  • 1970-01-01
  • 2013-01-03
  • 2017-07-29
相关资源
最近更新 更多