-1

Is it possible to write at the middle of a file for example I want to insert some string at the 5th position in the 2nd line of a file in c ? I'm not very familiar with some of C functions that are related to handling files , if someone could help me I would appreciate it

I tried using fputs but I couldn't insert characters at the desired location

mobin2357
  • 1
  • 1
  • Try using fgets(). After 5th iteration you can use fputs(). – ErlingHaaland Jan 06 '23 at 21:32
  • 1
    No, it is not possible in any language. *Inserting* something in the middle of the file would mean shifting the data that is coming after it physically on the disk. You can only replace existing data or append to it. – Eugene Sh. Jan 06 '23 at 21:32
  • Hey @mobin2357. Could you post a minimum example of what you have tried? It might help others assist in finding a solution. – MGM_Squared Jan 06 '23 at 21:33
  • I would write a new file (read prefix, write new content, write suffix) then rename new file to old file. If you need to do this a lot use a format that doesn't require you to rewrite the middle. Consider using SQLite instead of a custom format. – Allan Wind Jan 06 '23 at 21:37
  • 3
    You can seek to the middle of a file, and you can write, but you will overwrite what's there. Actually inserting (without overwriting anything) is either very difficult, or limited (e.g. to whole disk blocks), or impossible. For conventional purposes, rewriting a new file is the only way to go. – Steve Summit Jan 06 '23 at 21:44
  • You might take a look at [my `file_load()` function here for starters](https://stackoverflow.com/questions/71330345/c-function-to-load-file-contents-into-string-array/71346853#71346853). What you need to do is read in the whole file into RAM, then modify the contents, then write it back to a file with the modifications in-place. There are a variety of ways to do this, but the big takeaway to know is that you can't just "insert" something into a file. Rather, you have to read the whole file, modify it in RAM, then write the whole new thing. – Gabriel Staples Jan 06 '23 at 21:45
  • You could also do some on-the-fly variation of what I said above by reading the original file and writing it into a new file, making the necessary "insertions" as you go. Basically, you just write the new contents into a file with a similar name, then delete the old file and rename the new file to the old file's name when done. I suspect this (meaning: writing a new file and deleting the old, *or* just wiping the original file by rewriting the whole thing with the new contents) is how the "Save" button works in nearly all GUI text editor programs. – Gabriel Staples Jan 06 '23 at 21:54
  • Create a buffer (character array or allocated block of char) large enough to hold `original file + chars added - chars removed`. Read up to line 2 pos 5 into the buffer, add your new bytes to buffer, and read from last removed + 1 to end into buffer. Now write the buffer out to a new file and delete the old one. No way to add in the middle -- unless -- the bytes you remove and add are exactly the same number. Not worth the risk. Create what you need in a new buffer and then write it out to a new file. You can also just write the parts to a new file and skip the buffer --- up to you. – David C. Rankin Jan 07 '23 at 00:35

2 Answers2

0

Continuing from my comments above. Here's what I'd do:

  1. Create two large, static char[] buffers of the same size--each large enough to store the largest file you could possibly ever need to read in (ex: 10 MiB). Ex:
    #define MAX_FILE_SIZE_10_MIB (10*1024*1024)
    static char buffer_file_in[MAX_FILE_SIZE_10_MIB];
    static char buffer_file_out[MAX_FILE_SIZE_10_MIB];
    
  2. Use fopen(filename, "r+") to open the file as read/update. See: https://cplusplus.com/reference/cstdio/fopen/. Read the chars one-by-one using fgetc() (see my file_load() function for how to use fgetc()) into the first large char buffer you created, buffer_file_in. Continue until you've read the whole file into that buffer.
  3. Find the location of the place you'd like to do the insertion. Note: you could do this live as you read the file into buffer_file_in the first time by counting newline chars ('\n') to see what line you are on. Copy chars from buffer_file_in to buffer_file_out up to that point. Now, write your new contents into buffer_file_out at that point. Then, finish copying the rest of buffer_file_in into buffer_file_out after your inserted chars.
  4. Seek to the beginning of the file with fseek(file_pointer, 0, SEEK_SET);
  5. Write the buffer_file_out buffer contents into the file with fwrite().
  6. Close the file with fclose().

There are some optimizations you could do here, such as storing the index where you want to begin your insertion, and not copying the chars up to that point into buffer_file_in, but rather, simply copying the remaining of the file after that into buffer_file_in, and then seeking to that point later and writing only your new contents plus the rest of the file. This avoids unnecessarily rewriting the very beginning of the fie prior to the insertion point is all.

(Probably preferred) you could also just copy the file and the changes you insert straight into buffer_file_out in one shot, then write that back to the file starting at the beginning of the file. This would be very similar to @pm100's approach, except using 1 file + 1 buffer rather than 2 files.

Look for other optimizations and reductions of redundancy as applicable.

My approach above uses 1 file and 1 or 2 buffers in RAM, depending on implementation. @pm100's approach uses 2 files and 0 buffers in RAM (very similar to what my 1 file and 1 buffer approach would look like), depending on implementation. Both approaches are valid.

Gabriel Staples
  • 36,492
  • 15
  • 194
  • 265
0

open a new output file

read the input file line by line (fgets) writing each line out to a new file as you read.

When you hit the place you want to insert write the new line(s)

The carry on copy the old lines to the new file

close input and output

rename output file to input

pm100
  • 48,078
  • 23
  • 82
  • 145
  • @GabrielStaples not really, that tried to reasd the whole file into memory, this just needs one line in memoy at any time – pm100 Jan 07 '23 at 00:01