Click here to Skip to main content
14,207,596 members
Click here to Skip to main content
Add your own
alternative version

Stats

123.6K views
1.3K downloads
34 bookmarked
Posted 20 Oct 2002
Licenced

Using Text File Resources in VC++

, 21 Oct 2002
Rate this:
Please Sign up or sign in to vote.
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

Share

About the Author

DGoins
Web Developer
United States United States
Dwight N. Goins, MCT, MCSD, MCAD

Is a Microsoft Education Consultant with Hewlett-Packard. He teaches Microsoft Official Cirriculum with HP (formerly Extreme Logic).
He has also authored Courseware and Manuals for BizTalk Server 2004 and Microsoft Partners.

Dwight.Goins@hp.com
dngoins@hotmail.com

Comments and Discussions

 
GeneralMy vote of 4 Pin
Rajesh_Pa30-Jun-11 2:53
memberRajesh_Pa30-Jun-11 2:53 
GeneralProblem when there is more tha one xml file in the resources repo Pin
REDSERPENT72-Jun-09 4:20
memberREDSERPENT72-Jun-09 4:20 
I have used your method of loading an XML from the resources in VC++, the code works perfectly for 1 XML file. The problem is when I add more XML files to the resources, when I use LockResource on the handle for the first resource file in the list it seems that the returned pointer also points to the data in the second file is added to it and I'm guessing since XML files are not null terminated by default one should add a null data (0x00) at the end of the file. I don't know if this is the solution to the case, although it worked, but I was hoping that someone might have a better solution.
GeneralThis does not work Pin
screig16-Jun-08 3:37
memberscreig16-Jun-08 3:37 
GeneralCode does not work for me Pin
pdong4-Jan-06 5:34
memberpdong4-Jan-06 5:34 
Generallooks nice but doesn't work Pin
Anonymous8-Jun-05 8:03
memberAnonymous8-Jun-05 8:03 
GeneralRe: looks nice but doesn't work Pin
Dyaj29-Dec-05 3:49
memberDyaj29-Dec-05 3:49 
GeneralNicely done Pin
S.Cartwright20-Jun-04 5:23
memberS.Cartwright20-Jun-04 5:23 
GeneralRe: Nicely done Pin
S.Cartwright20-Jun-04 15:00
memberS.Cartwright20-Jun-04 15:00 
GeneralMultiple Resources of the same type Pin
MHillary22-May-04 0:11
memberMHillary22-May-04 0:11 
GeneralRe: Multiple Resources of the same type Pin
Brad Bruce20-Jun-04 9:56
memberBrad Bruce20-Jun-04 9:56 
GeneralRe: Multiple Resources of the same type Pin
mid=57416-Jan-05 17:54
membermid=57416-Jan-05 17:54 
GeneralInsert a few NULLs between Resources Pin
Mike O'Neill15-Feb-05 5:29
memberMike O'Neill15-Feb-05 5:29 
GeneralWOW! Pin
Beer8-Dec-02 16:34
memberBeer8-Dec-02 16:34 
GeneralRe: WOW! Pin
DGoins9-Dec-02 6:34
memberDGoins9-Dec-02 6:34 
GeneralDo it again Pin
Andreas Saurwein Franci Gonçalves22-Oct-02 23:32
memberAndreas Saurwein Franci Gonçalves22-Oct-02 23:32 
GeneralRe: Do it again Pin
Harold Bamford31-Oct-02 8:33
memberHarold Bamford31-Oct-02 8:33 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile
Web06 | 2.8.190612.1 | Last Updated 22 Oct 2002
Article Copyright 2002 by DGoins
Everything else Copyright © CodeProject, 1999-2019
Layout: fixed | fluid