0

i want to overwrite some part of string with other string in a file.

i want to overwrite in each line of file.

i wrote the below code, but this is not working please help.

suppose file has multiple line where one of the line containe:--- abcdefghioverwritefxyz89760

that should convert as below:-- abcdefghichangemadexyz89760

 char lineFileRecord [150];

 fp = fopen( "abc.txt","r+");

 while ( fgets (lineFileRecord , 150 , fp) != NULL )
 {
   char* sample;
   sample = strstr( lineFileRecord, "overwritef"); 

   //overwritef and changemade both have same size

   if( sample != NULL )
   {
      strncpy( sample, "changemade",10 ); // is the the correct way.

   }
 }

the above code in not replacing the contents. of the file. please correct me if i am wrong any.

thanks for reply.

ashutosh
  • 405
  • 6
  • 10
  • 3
    You need to write the altered data back to the file at the correct offset. – GWW Sep 04 '14 at 15:09
  • 1
    When the contents of the file is read into memory line by line, any changes made in memory are not reflected back to the file unless you take steps to write it. Note that you have to open the file for update, and you have to seek after each read _and_ after each write; when you switch between reading and writing or vice versa, there must be a seek operation (or equivalent — see the C standard) between the two I/O operations. If you had a memory mapped file, the rules would be different (starting with 'you would not use `fgets()` with a memory mapped file'). – Jonathan Leffler Sep 04 '14 at 15:18
  • can you please explain clearly? – ashutosh Sep 04 '14 at 15:29
  • 2
    The most common way to modify a file is to create a new, temporary, file and write to that. When everything is read and written without errors, then **and only then**, do you remove (or backup) the old file, and rename the new file to the old name. – Nisse Engström Sep 04 '14 at 15:48
  • This feels like cracking a walnut with an elevator. Have you considered a scripting language like perl? – Degustaf Sep 04 '14 at 21:32

2 Answers2

1

You always read/write files at a certain position. To make these changes, you need to jump back, overwrite, and jump back.

 char  lineFileRecord[150];
 FILE* fp = fopen("abc.txt","r+");
 long  posWrite = 0;
 long  posRead;

 while (fgets(lineFileRecord , 150 , fp) != NULL)
 {
    char* sample;
    sample = strstr(lineFileRecord, "overwritef"); 

    //overwritef and changemade both have same size

    if (sample != NULL)
    {
        // 1. Update your current lineFileRecord in memory.
        strncpy(sample, "changemade", 10);

        // 2. Remember where you were reading.
        posRead = ftell(fp);

        // 3. Jump back in the file to the beginning of your current lineFileRecord.
        //    This position was saved the previous time step 6 was executed.
        fseek(fp, posWrite, SEEK_SET);

        // 4. Now overwrite your file on disk! You were only changing the memory of
        //    of your program. And as you should know, memory and disk are
        //    different things. You need to overwrite the full lineFileRecord, 
        //    because ftell() does not give a clean byte position in text files.
        //    THANKS @chux!!!
        fwrite(lineFileRecord, 1, strlen(lineFileRecord), fp);

        // 5. Finally jump forward to where you are reading.
        fseek(fp, posRead, SEEK_SET);
    }

    // 6. Save the file position for the next overwrite.
    long posWrite = ftell(fp);
}

Remark: Stop using TABs in your code, it messes up indentation; always use spaces!

meaning-matters
  • 21,929
  • 10
  • 82
  • 142
  • 1
    Using a computed value for `fseek()` in a text file is a problem. Better to use a `ftell()` before the `fgets()` to know where to begin writing. `fseek()`: "For a text stream, either offset shall be zero, or offset shall be a value returned by an earlier successful call to the ftell function on a stream associated with the same file and whence shall be SEEK_SET. §7.21.9.2 4 – chux - Reinstate Monica Sep 04 '14 at 15:51
  • solution looks fine. but fp will not move along with char *sample. it will be always at zero. please correct me if i am wrong.. – ashutosh Sep 05 '14 at 12:02
  • @ashutosh I don't understand what you mean; I get the impression that you're (still) confusing things. What is the `it` that you think is always zero? – meaning-matters Sep 08 '14 at 13:03
0

Reading a file is the same as copying the contents of the file into memory*. You are modifying the copy of the contents, not the original.

You should either copy the content of entire file into memory, change that content, and then overwrite the entire file, or use the function calls like feek and fputs to modify parts of the file. How to write to a text file is explained in this question: Write to .txt file?

*Unless you are using something like memory mapped files. As a beginner, do not use memory mapped files, they are not trivial to use.

Community
  • 1
  • 1
Peter
  • 5,608
  • 1
  • 24
  • 43
  • "copy the content of entire file into memory" is a bit overkill. On many a system, the memory space (even virtual memory space) can be less than the file size. – chux - Reinstate Monica Sep 04 '14 at 16:44
  • @chux Premature Optimization for a special case. The question was about text files. Even a Raspberry Pi has 512 MB RAM. – Peter Sep 04 '14 at 16:47