Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Using Text File Resources in VC++

0.00/5 (No votes)
21 Oct 2002 1  
Use the Resource Editor to load a text file and use it inside a C++ app.

Introduction

This article explains how to use plain text files such as *.XML and others inside the MS Visual Studio Resource Editor for your C++ applications. The benefits to do so are:

  1. You don't have to worry about external files such as XML files your application may use, if they become corrupted by a virus or an experimental user.
  2. Your external files are kept in one central location; inside your binary application file. You are not concerned over where the location of your external files are.
  3. During deployment, there is no concern over where to place your external files, like what the user's computer directory structure is and etc; again, they are included inside your EXE or DLL application.

Now let's take a look at some disadvantages:

  1. The size of your EXE/DLL file will increase in size to account for resource file(s) you added.
  2. If your resource file changes, you have to re-load your resource into the Resource Editor to make sure the changes are reflected, and then re-compile your EXE/DLL program.
  3. The more complex your resource file is, and how it is used in your application, will undoubtedly mean that your code to use the resource file will be complex, and difficult to code.

So as we can see, there are certain situations where this might not be the best solution for the goal at hand. Yet, this does supply a viable solution to other type of applications.

In our sample program, we have a standard XML template file where for any given application, we want to maybe replace a re-occurring substring of data with another. This goal can be accomplished in many ways such as using the XML technologies, string search and replace methods by using code loops and etc. However, we want to keep things as simple as possible and use the standard template library.

Using the standard template library allows our code to be small, compact and extremely portable to other solutions. In any case, the only un-portable code would be the loading and retrieving of the resource text file itself: which is the basis for this article.

Shall we begin?

We start inside Visual Studio, creating a new console application type project and inserting a custom resource into our Resource Editor as the pictures show below:

Once we have our resource file added, we start our code by including the files and declarations here:

// Author: Dwight N. Goins 

// For Servell Computer Resources

// Date: 10/14/2002

// CreateXMLFiles.cpp : Defines the entry point for the console application.

//

#include "stdafx.h"


//Needed for Resource Files inside Resource Editor of XML data

#include <windows.h>


//Needed for low level file operations

#include <conio.h>

#include <io.h>

#include <sys/stat.h>


//Used to find pos of sub string in XML String

//resource

#include <string>

//Namespace for string operations

using namespace std;

Here is our main procedure and the source of the application:

int _tmain(int argc, _TCHAR* argv[])
{
  if (argc <= 2 || argc > 3) 
  {
    _tcprintf(_T("This Program's Expected Usage is:\n" 
          " %s PathDefault PathToWriteXmlFiles"), argv[0]);
    return 1;
  }

    //Getting Arguments

    LPTSTR sArgv = argv[1];
    LPTSTR sArgv2 = argv[2];

    //Getting Resource Info

    //And Storing as String Data

        //Once the Resource Editor has store our file.

        // Open up the resouce.h file in a text editor to

        // see what the number assignment for the resource is

        // in this case it is 103, this will be the resources

        // name internally

    TCHAR  sResName[5]  = _T("#103");

        // Now because we choose to represent the resource type

        // as a custom

        // type we just tell use this type to locate the

        // resource in the application


    TCHAR sRestype[13] = _T("TIMELISTINGS");
    HRSRC hres = FindResource(NULL, sResName, sRestype);
       if (hres == 0)
       { 
      _tcprintf(_T("An Error Occurred.\n Could Not Locate Resource File."));
        return 1;
        }
        
        //If resource is found a handle to the resource is returned

        //now just load the resource

    HGLOBAL    hbytes = LoadResource(NULL, hres);
        
        // Lock the resource

    LPVOID pdata = LockResource(hbytes);

        //Convert the resource text file to data we can use

    LPBYTE sData = (LPBYTE)pdata;
    LPTSTR sXml = (LPTSTR)sData;



        //That's it!

        //The rest of the application follows...

    size_t iArgLen = _tcslen(sArgv2);
    size_t iLen = _tcslen(sXml);
    string strXml = string(sXml);
    LPTSTR sDefault = sArgv;
    size_t iDefLen = _tcslen(sDefault);
    size_t iPos = strXml.find(string(sDefault), 0);

    //Determine the size to write the file

    //If length is greater, then nothing to worry about

    //if smaller, then we must calculate size to shrink

    //file in order to cut off excess superflous data

    size_t iSizeToWrite = (iDefLen > iArgLen ? 
            (iLen -(iDefLen - iArgLen) * 15) : iLen);

    if (iPos > iLen || iPos < 0)
    {
        _tcprintf(_T("Could Not Find %s inside" 
          " the Xml Resource Structure"), argv[1]);
        return 2;
    }

    //Using the Replace Function To change 

    //String Data

    strXml.replace(iPos ,iDefLen, sArgv2);
    
    //Now Loop Through until end of String Resource

    //To Replace the whole file

    while (iPos < iLen )
    {
    iPos = strXml.find(string(sDefault), 0);
    if (iPos > iLen)
        break;
    strXml.replace(iPos ,iDefLen, sArgv2);
    }

    //Get Default String for Replacement

    LPTSTR sReplace = new TCHAR[_tcslen(sArgv2)];
    _tcscpy(sReplace, sArgv2);

    //Set 9am file string

    LPTSTR s9amFile = _tcsncat(sArgv2, _T("\\9AM.xml"),
                iLen + 10);

    //Create the file for writting

    int fh = _tcreat(s9amFile, _S_IWRITE );
    if (fh == -1)
    { 
      _tcprintf(_T("An Error Occurred.\n " 
        "9AM XML File Could Not Be Created."));
        return 3;
    }
    //Write the String Data to file

    int iBytesWritten = _write(fh, (LPVOID)strXml.c_str(),
            iSizeToWrite);
    if (iBytesWritten == 0)
    {
        _tcprintf(_T("An Error Occurred.\n 9AM XML" 
            " File Could Not Be Written To."));
        _close(fh);
        return 4;
     }
        
        //Close the file

    _close(fh);

    //Repeat for 9PM and 3PM files

    _tcscpy(sArgv2, sReplace);
    LPTSTR s9pmFile = _tcsncat(sArgv2, _T("\\9PM.xml"),
            iLen + 10);
    fh = _tcreat(s9pmFile, _S_IWRITE );
    if (fh == -1)
    { 
       _tcprintf(_T("An Error Occurred.\n 9PM"
              " XML File Could Not Be Created."));
       return 3;
    }

    iBytesWritten = _write(fh, (LPVOID)strXml.c_str(),
          iSizeToWrite);
    if (iBytesWritten == 0)
    {
      _tcprintf(_T("An Error Occurred.\n " 
          "9PM XML File Could Not Be Written To."));
      _close(fh);
      return 4;
    }
    _close(fh);
    _tcscpy(sArgv2,sReplace);
    LPTSTR s3pmFile = _tcsncat(sArgv2, _T("\\3PM.xml"),
         iLen + 10);
     fh = _tcreat(s3pmFile, _S_IWRITE );
    if (fh == -1)
    { 
      _tcprintf(_T("An Error Occurred.\n 3PM" 
                 " XML File Could Not Be Created."));
      return 3;
    }

     iBytesWritten = _write(fh, (LPVOID)strXml.c_str(), 
             iSizeToWrite);
    if (iBytesWritten == 0)
    {
        _tcprintf(_T("An Error Occurred.\n "
                "3PM XML File Could Not Be Written To."));
           _close(fh);
        return 4;
    }

    _close(fh);

    //Program Completed Successful

    _tcprintf(_T("Program Completed Successfully."
           "\n 3 Files were written to:\n%s\n%s\n%s\n"),
           s9amFile, s3pmFile, s9pmFile);
    return 0;

}

That's all folks for now.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here