Easy way to embed a text database

Hi, can someone please help clarify what would be the right way to embed a text file into the exe file? I have several text databases. I do not want them to remain as separate files, and would like them to be include into the exe. In Java, I can simply copy the text files into the project resource folders and then Java will compile them together with the executable. Is there a similarly simple and cross-platform way in C++? Thanks so much!
Have you tried compiling the text file in the resource folder for the .exe? If it doesnt work, you can simply change d file xtension for your text file of database, I use .db mostly. But i see no reason why the txt files shouldnt compile alongside d whole executable.
I may be doing something wrong but whenever I move the exe file from the project folder, it does not find the text file. So, the text file is obviously not embedded. Are there any settings in Code::Blocks I am missing?

Thanks!
What steps have you taken?

And which compiler (not IDE) and platform(s) are you working with?

The usual Windows-specific way would be to bind the files into the resource segment. But it might be possible to use the objcopy approach used for Linux binaries (using the MinGW version of objcopy.)

Embedding a File in an Executable, aka Hello World, Version 5967
http://www.linuxjournal.com/content/embedding-file-executable-aka-hello-world-version-5967

Andy
Last edited on
Andy.
Right now, I use GNU GCC compiler in Code::Blocks under Windows. I also intend to do the same project in XCode in OSX.

I created a resource.h file

1
2
#define TEXTFILE   256
#define IDR_DATA1  101 



I also created a resource.rc file

1
2
#include "resource.h"
IDR_DATA1 TEXTFILE "indexCargo.txt"


Then I applied the following code in the main:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46

#include <cstdlib>
#include <ctime>
#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>
#include <windows.h>
#include <cstdio>

#include "resource.h"


using namespace std;


int main()  {

    string key = "300";

    string result;

    std::string line ;

    HRSRC hRes = FindResource(0, MAKEINTRESOURCE(IDR_DATA1), MAKEINTRESOURCE(MYRESTYPE));

    while( std::getline( hRes, line ) && line.find(key) != 0 );

    if( line.find(search_string) != 0 )
    {
        std::cerr << "file was not found\n" ;
        result = "N/A" ;
    }

    else{
        result = line + '\n' ;
    }

    hRes.close();

    cout << "The result is :" << result << endl;

    system("PAUSE");
    return 0;

}


Please note that the only experience I have is with Java, and I tried to replicate what I have found on Internet. Unfortunately, there is not a lot and the above is obviously wrong as it is not working.

Thank you for the patience.
More or less right.

The resource side of things is fine, but it's a bit more work to read the data.

To save typing, see the answer here:

how to use a resource file (txt - tab delimited) as a data source for win32 application
http://stackoverflow.com/questions/1994576/how-to-use-a-resource-file-txt-tab-delimited-as-a-data-source-for-win32-appl

Andy
Andy. Thanks a lot! Almost there... (Frankly, this topic, in my opinion is so under-resourced.)

Anyways. I have the following code now.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>
#include <windows.h>
#include <cstdio>

#include "resource.h"


using namespace std;

string getCargoIndex(string keyIn);


int main()  {

    string key = "300";
    string cargoResult;

    cargoResult = getCargoIndex(key);

    cout << cargoResult << endl;

    system("PAUSE");
    return 0;

}



string getCargoIndex(string keyIn)
{
    HGLOBAL     res_handle = NULL;
    HRSRC       res;
    char *      res_data;
    DWORD       res_size;
    HINSTANCE   hInst;

    string getText;
    string result;
    string line;


    res = FindResource(0, MAKEINTRESOURCE(DATASET_CARGO), RT_RCDATA);
    if (!res)
    //    return;
        cout << "Not found" << endl;
    res_handle = LoadResource(NULL, res);
    if (!res_handle)
    //    return;
        cout << "Not found" << endl;
    res_data = (char*)LockResource(res_handle);
    res_size = SizeofResource(NULL, res);

    while( getline( res_data, line ) && line.find(keyIn) != 0 );

        if( line.find(keyIn) != 0 )
        {
            sthResd::cerr << "file was not found\n" ;
            result = "N/A" ;
        }

        else{
            result = line + '\n' ;
        }
    return result;
}


Without the lines starting from "while..." it works perfectly well now, that is it prints the entire dataset. However, there is some problem in this line:

 
while( getline( res_data, line ) && line.find(keyIn) != 0 );


Error: no matching function for call.

I cannot call the getline function like this?

Oh, and one more silly question. So, if I have several more datasets plus a bunch of jpg files to incorporate into my application, can I have all of them in one resource file? Is it a good practice or should I have them in different resource files?
Thank you so much!
Last edited on
I cannot call the getline function like this?

Surprisingly enough, no.

Why did you think getline would work with a char* when it needs an std::istream?
http://www.cplusplus.com/reference/string/string/getline/?kw=getline )

If you want to use getline, use (the char*) res_data to initialise an istringstream
http://www.cplusplus.com/reference/sstream/istringstream/

i.e. replace

while( getline( res_data, line ) && line.find(keyIn) != 0 );

with

1
2
3
    istringstream iss(res_data); // from <sstream>

    while( getline( iss, line ) && line.find(keyIn) != 0 );


can I have all of them in one resource file?

Yes, that makes sense here; unless you have lots of resource (which is prob a bad sign) it's best to stick to a single .rc file (as it's easy to see what's going on.)

1
2
3
4
5
#include "resource.h"
IDR_DATA1 TEXTFILE "indexCargo.txt"
IDR_DATA2 TEXTFILE "indexShips.txt"
IDR_DATA3 TEXTFILE "indexPorts.txt"
// etc 


Andy

Last edited on
Andy. You have been extremely helpful, as always. Thank you so much!!
Topic archived. No new replies allowed.