Common File Tasks — Search and Replace, and Append

A class to do search and replace functions within a file and add a line to a file.

Environment: MFC Visual C++ (6.0)

After re-implementing certain file functions a few times, I thought it would be worthwhile to make a class that would do some common tasks. This class basically does two things:

  1. Replace: Searches the specified file, replacing all occurences of the specified search string with the specified replacement string. An optional parameter is case-sensitivity. The return value is the number of replacements made.
  2. InsertLineIntoFile: Adds the specified entry to the specified file. Optional paramters are case-sensitivity and if the string should be added only if the entry does not already exist or not. The return value is non-zero if the line was added.

The class is really pretty simple. The code should be relatively easy to understand. I do not combine five statements into one and I try to use descriptive variable names.

An emphasis was placed on readability and functionality versus efficiency.

Extensive use was made of the CString functions.

To implement the SnR (Search and Replace) class, you just add SnR.cpp and SnR.h to your project and add #include “SnR.h” to your source code file.

A sample program/project is provided to demonstrate the use of the class.

I have put lots of comments in the code, so this is the end of the commentary. The .h and .cpp file are shown here and are available for download at the bottom, either by themselves or in the sample project.

Here is SnR.h:


// SnR (Search and Replace Class) written by James Moody
// Functions:
// Replace: Replacing all occurences of a string in a file
// case sensitive or not
// returns the number of changes made
// DoLineReplacement: Replacing all occurences of a sub-string
// in a string
// case sensitive or not
// returns the number of changes made
// Was created to support the Replace Function but could be
// used on its own
// Takes a pointer to the string to be modified
// InsertLineIntoFile
// Targeted toward updating configuration
// files where line entries
// should be added if they do not already exist
// case sensitive or not.

class SnR
{
public:
int Replace( CString TheFile,
CString SearchString,
CString ReplaceString,
int iCheckCase = 0);
int DoLineReplacement(CString *LineString,
CString SearchString,
CString ReplaceString,
int iCheckCase = 0 );
int InsertLineIntoFile(CString TheFile,
CString InsertLine,
int iOnlyIfNotThere = 1, int iCheckCase=0);
private:

char c;
CString SearchTemp;
CString ReplaceTemp;
CString LineStringTemp;
int iSearchToCompare;
int iReturn;
int iStringStart;
int iRightCharacters;;
int iLengthSearch;
CString TempFile;
FILE* pSearchFile;
FILE* pTempFile;
CString LineFromFile;
CString LineToFile;
CString RightPortion;

};


Here is SnR.cpp:


#include “stdafx.h”
#include “SnR.h”

// Class Name……: SandR
// Desription……: Search and Replace in a file, and add to a file
// Author, email, date….: James Moody james_moody@yahoo.com
// 28 May 2002
// Public Member Functions (Methods):
// Replace Does a search and replace on the contents
// of a file.
// Has a parameter to specify case-sensitive or not.
// InsertLineIntoFile Adds the string to the file
// Has a parameter to specify case-sensitive or not.
// Has a parameter to specify if the line will be added
// if it already exists.
// DoLineReplacement Is called by Replace, so it could be a
// private function, but
// could be useful by itself. Within a string,
// replaces every occurence of the search string
// with the replace string.

int SnR::DoLineReplacement(CString* LineString,
CString SearchString,
CString ReplaceString,
int iCheckCase)
{
iLengthSearch = SearchString.GetLength();
int iReturn2=0; // the return value
SearchTemp = SearchString;
ReplaceTemp = ReplaceString;
LineStringTemp = *LineString;
// If case insensitive, make all upper case before comparing
// Use a temp string for comparing and make changes
// to the original string
if( ! iCheckCase)
{
SearchTemp.MakeUpper();
// ReplaceTemp.MakeUpper();
LineStringTemp.MakeUpper();

}

// will do the while loop until no more matches with the
// search string are found
// iStringStart (if not -1) will hold the location where
// the matching string starts

while( (iStringStart= LineStringTemp.Find(SearchTemp)) != -1)
{
LineToFile = LineString->Left(iStringStart);
// now LineToFile has everything up to where
//the search string starts
LineToFile += ReplaceString;
// now LineToFile has the replace string inserted
iRightCharacters = LineString->GetLength() –
iStringStart – iLengthSearch;
RightPortion = LineString->Right(iRightCharacters);
LineToFile += RightPortion;
// now LineToFile has the string with the first
// occurence replaced
*LineString = LineToFile;
// now LineString has the string with the first occurence replaced
LineStringTemp = *LineString;
iReturn2++;
// If case insensitive, make all upper case before comparing
// Use a temp string for comparing and make changes
// to the original string
if(! iCheckCase)
{

LineStringTemp.MakeUpper();
} // if(iCheckCase)

} // while (iStringStart= LineFromFile….
return iReturn2;
}

// Replace
// Replaces in ‘TheFile’ each occurrence of ‘ReplaceString’
// with ‘SearchString’
// iCheckCase, if Non-Zero makes the determination case sensitive
// and defaults to 0
int SnR::Replace( CString TheFile,
CString SearchString,
CString ReplaceString,
int iCheckCase)
{
iReturn=0;
iStringStart = 0;
iRightCharacters = 0;;
iLengthSearch = SearchString.GetLength();
TempFile = “tempSnr.txt”;
pSearchFile = 0;
pTempFile = 0;
LineFromFile = “”;
LineToFile = “”;
RightPortion = “”;

if(iLengthSearch < 1 )
return 0;

// going to open the search file
if (pSearchFile =fopen(TheFile,”r”))
{
// going to open the temp file
if(pTempFile = fopen(TempFile,”w”))
{
while ( (c=getc(pSearchFile) )!= EOF) // filling the
//string with a line from the file.
{
LineFromFile += (CString) c;
if((c != 10) && (c !=13) )
{

}
else
{ // found a newline or carriage return character
// so now analyze the line
// call DoLineReplacement on the newly aquired line
iReturn += DoLineReplacement(&LineFromFile,
SearchString,
ReplaceString,
iCheckCase);

LineToFile = LineFromFile;
// print the possibly modified line to the temporary file
fprintf(pTempFile,LineToFile);
LineFromFile = “”;
}// if((c != 10) && (c !=13) )

} //while (c=getc(TheFile) != EOF)

// in case the last line did not have a cr or ln will
//analyze the line
iReturn += DoLineReplacement(&LineFromFile,
SearchString,
ReplaceString,
iCheckCase);

LineToFile = LineFromFile;
fprintf(pTempFile,LineToFile);
LineFromFile = “”;
// done dealing with the last line

fclose(pTempFile);
} //if(pTempFile = fopen(TempFile,”w”))
else
{

} // else of if(pTempFile = fopen(TempFile,”w”))
fclose(pSearchFile);
} //if (pSearchFile =fopen(TheFile,”r”))
else
{
AfxMessageBox(“Unable to open the file.”);
} // else of if (pSearchFile =fopen(TheFile,”r”))

if (iReturn)
{ // If any modifications were made
// Now we will copy the newly created tempfile that
// has the modifications back to
// the original file, manually
// It’s true there is a CFile class member function
// called rename. We could have used that, but used this
// general method when creating the file anyway
// so there should be no problem using this method
// to rename the file back
if(pTempFile = fopen(TempFile,”r”))
{
if (pSearchFile =fopen(TheFile,”w”))
{
while ( (c=getc(pTempFile) )!= EOF)
{
putc(c,pSearchFile);
}// while ( (c=getc(pSearchFile) )!= EOF)
fclose(pSearchFile);
} // if (pSearchFile =fopen(TheFile,”w”))
fclose(pTempFile);
} // if(pTempFile = fopen(TempFile,”r”))
} // if (iReturn)
// deleting the temporary file that had the changes
DeleteFile(TempFile);
return iReturn;

} // BOOL SnR::Replace(CString TheFile, CString SearchString,
//CString ReplaceString)

// InsertLineIntoFile
// This Function works on a ‘line’ basis.
// It inserts the line in the end of the file
// The Parameter iOnlyIfNotThere, if Non-Zero will only add
// the line if it was not found in the file
// The Parameter iCheckCase, if Non-Zero will make the
// determination
// case sensitive
int SnR::InsertLineIntoFile(CString TheFile, CString InsertLine,
int iOnlyIfNotThere, int iCheckCase)
{
iReturn=0;
CString InsertLineTemp = InsertLine;

int iFoundLine=0;
// If case insensitive, make all upper case before comparing
// Use a temp string for comparing and make changes to
// the original string
if( ! iCheckCase)
{
InsertLineTemp.MakeUpper();
}

LineFromFile = “”;
if(iOnlyIfNotThere) // need to find out if the string exists
//in the file if the parameter is ‘on’
if (pSearchFile =fopen(TheFile,”r”))
{

while ( (c=getc(pSearchFile) )!= EOF)
{
LineFromFile += (CString) c;
if((c != 10) && (c !=13) )
{
}
else
{
if( ! iCheckCase)
{
LineFromFile.MakeUpper();

}

if(InsertLineTemp == LineFromFile)
{
iFoundLine=1;
} // if(InsertLine == LineFromFile)
// Maybe a newline or whitespace prevented a
// match so trim those and check again
LineFromFile.TrimRight(“\n”);
LineFromFile.TrimRight();
if(InsertLineTemp == LineFromFile)
{
iFoundLine=1;
} // if(InsertLine == LineFromFile)

LineFromFile = “”;
}// if((c != 10) && (c !=13) )

} //while (c=getc(TheFile) != EOF)

// in case the last line did not have a cr or
// ln will analyze the line
if( ! iCheckCase)
{
LineFromFile.MakeUpper();
}

if(InsertLineTemp == LineFromFile)
{
iFoundLine=1;
} // if(InsertLine == LineFromFile)
// Maybe a newline or whitespace prevented a match
// so trim those and check again
LineFromFile.TrimRight(“\n”);
LineFromFile.TrimRight();
if(InsertLineTemp == LineFromFile)
{
iFoundLine=1;
} // if(InsertLine == LineFromFile)

LineFromFile = “”;
// done dealing with the last line

fclose(pSearchFile);

} //if (pSearchFile =fopen(TheFile,”r”))
else
{
AfxMessageBox(“Unable to open the file.”);
} // else of if (pSearchFile =fopen(TheFile,”r”))

// now we will add the line if it was not found or if we are
// supposed to add it either way
if( (! iFoundLine ) || ( ! iOnlyIfNotThere) )
{
if (pSearchFile =fopen(TheFile,”a”))
{
fprintf(pSearchFile,”\n”);
fprintf(pSearchFile,InsertLine);
fprintf(pSearchFile,”\n”);
fclose(pSearchFile);
iReturn=1;
} // if (pSearchFile =fopen(TheFile,”r”))

} // if( (! iFoundLine ) || ( ! iOnlyIfNotThere) )

return iReturn;
}

Downloads

Download demo project – SnR_demo.zip – 16 Kb

Download source -SnR_src.zip – 3 Kb

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read