【问题标题】:Embed data in a C++ program在 C++ 程序中嵌入数据
【发布时间】:2010-09-09 12:19:09
【问题描述】:

我有一个使用 SQLite 的 C++ 程序。我想将 SQL 查询存储在一个单独的文件中——一个纯文本文件,不是一个源代码文件——但将该文件像资源一样嵌入到可执行文件中。

(这必须在 Linux 上运行,所以据我所知,我无法将其存储为实际资源,但如果它适用于 Windows,那就完美了。)

是否有任何简单的方法可以做到这一点,或者它是否会有效地要求我为 Linux 编写自己的资源系统? (很容易,但需要更长的时间。)

【问题讨论】:

    标签: c++ linux sqlite


    【解决方案1】:

    您可以使用 objcopy 将文件的内容绑定到您的程序可以使用的符号。例如,请参阅here 了解更多信息。

    【讨论】:

      【解决方案2】:

      使用宏。从技术上讲,该文件将是 源代码 文件,但它看起来不像这样。 示例:

      //queries.incl - SQL queries
      Q(SELECT * FROM Users)
      Q(INSERT [a] INTO Accounts)
      
      
      //source.cpp
      #define Q(query) #query,
      char * queries[] = {
      #include "queries.incl"
      };
      #undef Q
      

      稍后您可以通过同一个文件对该文件进行各种其他处理,假设您想要拥有它们的数组和哈希映射,您可以重新定义 Q 来完成另一项工作并完成它。

      【讨论】:

        【解决方案3】:

        您始终可以编写一个小程序或脚本来将您的文本文件转换为头文件,并将其作为构建过程的一部分运行。

        【讨论】:

          【解决方案4】:

          这是我们用于跨平台嵌入文件的示例。 这很简单,但可能对你有用。

          您可能还需要更改它在 escapeLine 函数中处理换行符的方式。

          #include <string>
          #include <iostream>
          #include <fstream>
          #include <cstdio>
          
          using namespace std;
          
          std::string escapeLine( std::string orig )
          {
              string retme;
              for (unsigned int i=0; i<orig.size(); i++)
              {
                  switch (orig[i])
                  {
                  case '\\':
                      retme += "\\\\";
                      break;
                  case '"':
                      retme += "\\\"";
                      break;
                  case '\n': // Strip out the final linefeed.
                      break;
                  default:
                      retme += orig[i];
                  }
              }
              retme += "\\n"; // Add an escaped linefeed to the escaped string.
              return retme;
          }
          
          int main( int argc, char ** argv )
          {
              string filenamein, filenameout;
          
              if ( argc > 1 )
                  filenamein = argv[ 1 ];
              else
              {
                  // Not enough arguments
                  fprintf( stderr, "Usage: %s <file to convert.mel> [ <output file name.mel> ]\n", argv[0] );
                  exit( -1 );
              }
          
              if ( argc > 2 )
                  filenameout = argv[ 2 ];
              else
              {
                  string new_ending = "_mel.h";
                  filenameout = filenamein;
                  std::string::size_type pos;
                  pos = filenameout.find( ".mel" );
                  if (pos == std::string::npos)
                      filenameout += new_ending;
                  else
                      filenameout.replace( pos, new_ending.size(), new_ending );
              }
          
              printf( "Converting \"%s\" to \"%s\"\n", filenamein.c_str(), filenameout.c_str() );
          
              ifstream filein( filenamein.c_str(), ios::in );
              ofstream fileout( filenameout.c_str(), ios::out );
          
              if (!filein.good())
              {
                  fprintf( stderr, "Unable to open input file %s\n", filenamein.c_str() );
                  exit( -2 );
              }
              if (!fileout.good())
              {
                  fprintf( stderr, "Unable to open output file %s\n", filenameout.c_str() );
                  exit( -3 );
              }
          
              // Write the file.
              fileout << "tempstr = ";
          
              while( filein.good() )
              {
                  string buff;
                  if ( getline( filein, buff ) )
                  {
                      fileout << "\"" << escapeLine( buff ) << "\"" << endl;
                  }
              }
          
              fileout << ";" << endl;
          
              filein.close();
              fileout.close();
          
              return 0;
          }
          

          【讨论】:

            【解决方案5】:

            它有点难看,但你总是可以使用类似的东西:

            const char *query_foo =
            #include "query_foo.txt"
            
            常量字符 *query_bar =
            #include "query_bar.txt"
            

            其中 query_foo.txt 将包含引用的查询文本。

            【讨论】:

            • 如果它包含一个新行怎么办?
            【解决方案6】:

            我已经看到这是通过将资源文件转换为 C 源文件来完成的,该文件只定义了一个包含十六进制格式的资源文件内容的 char 数组(以避免恶意字符出现问题)。这个自动生成的源文件然后被简单地编译并链接到项目。

            应该很容易实现转换器来为每个资源文件转储 C 文件,以及编写一些用于访问资源的外观函数。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2011-05-05
              • 2013-04-24
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多