Link to home
Start Free TrialLog in
Avatar of NikWhitfield
NikWhitfield

asked on

Open a file and replace a string

Hi,

I know nothing about C, and need to write a small script using it. Basically I need to find a file on a machine (TNSNames.ora) and replace one of the entries in it. A bit of handling should be done if the file isn't in the C:\orawin95\net80\admin directory, or if the search text is not found.

I don't want to learn C, so if someone could write the correct code for me, it would be most appreciated.

Thanks, Nik.
Avatar of marcjb
marcjb
Flag of United States of America image

/*
Not the most efficient method, but it should work.  The file is opened, and so is a temp file.  All lines that don't match the string to be replaced are copied to the temp file, and then they are copied back.  The temp file is automatically removed when closed.
This is ANSI C, so you should have no trouble compiling.  One thing to note is that the string compare function is case sensitive.  
Hope this helps.
*/


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define   MAX   1024

int main()
{
FILE *f;
FILE *tmp;
char aLine[MAX];
char toReplace[MAX];
int found = 0;

/* Try and open the file */
if ( (f = fopen("C:\\orawin95\\net80\\admin\\TNSNames.ora", "r")) == NULL )
    {
    printf("\nERROR: Failure to open file TNSNames.ora\n");
    exit(EXIT_FAILURE);
    }

/* Open a temporary file */
if ( (tmp = tmpfile()) == NULL )
    {
    printf("\nERROR: Failure to open temp file\n");
    exit(EXIT_FAILURE);
    }

/* Get the string to replace (This could be done many ways) */
printf("\nEnter the string to replace\n");
fgets(toReplace, MAX, stdin);  /* Keep the newline */

/* Cycle through file to find string */
while ( fgets(aLine, MAX, f) != NULL )
    {
    if ( strcmp(aLine, toReplace) == 0 )
      {
      found = 1;
      continue;
      }
    /* else, copy the line to a temp file */
    fprintf(tmp, "%s", aLine);
    }

/* Close TNS and go to beginning of temp file */
fclose(f);
rewind(tmp);

/* Re-open file to truncate data, and copy new data from temp file */
if ( (f = fopen("C:\\orawin95\\net80\\admin\\TNSNames.ora", "w")) == NULL )
    {
    printf("\nERROR: Failure to open file TNSNames.ora\n");
    exit(EXIT_FAILURE);
    }

while ( fgets(aLine, MAX, tmp) != NULL )
    fprintf(f, "%s", aLine);

if ( found == 0 )
    printf("\nString not found in file\n");
else
    printf("\nString found and removed\n");

fclose(f);
fclose(tmp);
return 0;
} /* main */
Avatar of NikWhitfield
NikWhitfield

ASKER

I have run this code and it simply says "String not found in file", when I know that it is in the file.

Also, the user shouldn't have to input the phrase.

It can be hardwired as :

Find - "uk-finance-as01"
Replace with - "uk-lop-as01"

Another issue - the find phrase will be in amongst other text, so replacing lines is no good.
I have run this code and it simply says "String not found in file", when I know that it is in the file.

Also, the user shouldn't have to input the phrase.

It can be hardwired as :

Find - "uk-finance-as01"
Replace with - "uk-lop-as01"

Another issue - the find phrase will be in amongst other text, so replacing lines is no good.
If you mean the following:
replace: get
string: together
result: toher

use the strstr function to determine one string is in another, and then shift the string over.

For example, assume that the string to replace is still in a variable called toReplace.
Also, delace a character pointer:
char *ptr;



/* Add this line if letting the user input the string to find, else, just hard code the string to replace */

strtok(toReplace, "\n"); /* Don't keep the newline */

/* CHANGE TO THE FOLLOWING */

/* Cycle through file to find string */
while ( fgets(aLine, MAX, f) != NULL )
    {
    if ( (ptr = strstr(aLine,toReplace)) != NULL )
      {
      /* substring found.  Now replace */
      memmove(ptr, ptr + strlen(toReplace),
            1 + strlen(ptr + strlen(toReplace)) );
      /* add 1 to grab the null terminator */
      found = 1;
      }
    fprintf(tmp, "%s", aLine);
    }

No this is not what I mean. I want to do the equivalent of the VB 'Replace' command.

String to find: uk-finance-as01
Replace with : uk-lop-as01
File : "(stuff,(uk-finance-as01),)"

Result : "(stuff,(uk-lop-as01),)"
ASKER CERTIFIED SOLUTION
Avatar of marcjb
marcjb
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Much better!

One last refinment though (I'll add extra points for the new requirements!).

I just need it to display a success or failure MessageBox.

i.e. If the text is changed OK, then show a messagebox saying something like "File updated successfully".
And if it fails for any reason (e.g. if the file is not found), then messagebox "File update failed. Please phone OM support."

Cheers!
Sorry, but I'm not familier with the Windows API, so I don't know how to do messages boxes.  
Header file: Winuser.h
Windows CE versions: 1.0 and later


Syntax
int MessageBox(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption,
UINT uType);

Parameters
hWnd

[in] Handle to the owner window of the message box to be created. If this parameter is NULL, the message box has no owner window.

lpText

[in] Long pointer to a null-terminated string that contains the message to be displayed.

lpCaption

[in] Long pointer to a null-terminated string used for the dialog box title. If this parameter is NULL, the default title “Error” is used.

uType

[in] Specifies a set of bit flags that determine the contents and behavior of the dialog box. This parameter can be a combination of flags from the following groups of flags.




You can find different types of msgboxes in the help of msdn. this is selected from the last parameter.
Does this need to be in C?
Can it be C++?  If so, I'll look into
converting marcjb's code into a short
MFC program (i'm still learning MFC,
so this can be practice for me).  I
think marcjb spent some good time
writing that program and would like to
see him getting the points.
Thank you x2 :)

Nik,
When I was copying the source over I forgot to include the following two lines before the return that ends the program.


fclose(f);
fclose(tmp);


They aren't really needed as the program ending should automatically close the files, but it is good practice.
does this need to be C, C++ or what ever?
When most other tools may do this job in a single, simple line, like
    sed -e 's/uk-finance-as01/uk-lop-as01/g' TNSNames.ora > newfile
or
  perl -i -pe  's/uk-finance-as01/uk-lop-as01/g' TNSNames.ora
even NT's cmd.exe may do it in 2 or 3 lines.
Any language is OK as long as I don't need to distribute Dlls or anything, just an executable.
Any language is OK as long as I don't need to distribute Dlls or anything, just an executable. So C, C++ etc are fine.

ahoffman - what's sed?
By the way, I have no idea why it's printing my comments twice!

An add on to my last comment - as long as no ditribution files are needed AND it notifies the user as to whether it was a success or failure are the 2 main requirements. I don't care how this is achieved. The platform will be Windows 95 / NT.
Thanks for the work. I managed to implement the rest myself.
Thank you, and good luck.
sed is some of these tiny magic tools available on any UNIX, but ported to M$ world too