Read/Write to file

M

Martin Svensson

Hello!

I need some help/recommendations on how to do the following.
I have a program that writes an IP address two control numbers and a
date to file, on one line. It's a basic text file and it looks like this:

----- beginning of file -----
192.168.0.1 0 0 2004-08-01
192.168.0.2 1 0 2004-08-21
192.168.0.4 0 1 2004-08-12
-------- end of file --------

I know how to write data to a file. But what if I want to change data in
this file, for instance, on line two I want to change the first control
number to a 0 instead of a 1. How would I do this?

Thank you for an honest answer.

Best regards
Martin
 
J

Jens.Toerring

Martin Svensson said:
I need some help/recommendations on how to do the following.
I have a program that writes an IP address two control numbers and a
date to file, on one line. It's a basic text file and it looks like this:
----- beginning of file -----
192.168.0.1 0 0 2004-08-01
192.168.0.2 1 0 2004-08-21
192.168.0.4 0 1 2004-08-12
-------- end of file --------
I know how to write data to a file. But what if I want to change data in
this file, for instance, on line two I want to change the first control
number to a 0 instead of a 1. How would I do this?

As long as you don't want to insert something into the file but just
overwrite parts of it it's rather simple, the following should do
that (assuming the file is names "data.txt" and leaving out all the
checks you _should_ do):

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

int main( void )
{
FILE *fp = fopen( "data.txt", "rb+" );

while ( fgetc( fp ) != '\n' ) /* go to start of 2nd line */
/* empty */ ;
fseek( fp, 12, SEEK_CUR ); /* go to char to be changed */
fprintf( fp, "0" );
fclose( fp );
return EXIT_SUCCESS;
}

What you can't do is inserting more data then are already there, in
that case you would have to create a new file, copying everything
you want to keep and interspersed with the changes.

Regards, Jens
 
E

Eric Sosman

Martin said:
Hello!

I need some help/recommendations on how to do the following.
I have a program that writes an IP address two control numbers and a
date to file, on one line. It's a basic text file and it looks like this:

----- beginning of file -----
192.168.0.1 0 0 2004-08-01
192.168.0.2 1 0 2004-08-21
192.168.0.4 0 1 2004-08-12
-------- end of file --------

I know how to write data to a file. But what if I want to change data in
this file, for instance, on line two I want to change the first control
number to a 0 instead of a 1. How would I do this?

Open the file for update ("r+" mode), read all the
data up to but not including the '0' you want to change,
do an fseek(stream, 0, SEEK_CUR), and then write the '1'.
(The fseek() looks like a no-op, but you must do a file-
positioning operation when changing from input to output.)

*However*, this technique relies on the fact that '0'
and '1' are the same length. If you wanted to change the
0 to 12345 (or change 12345 to 0) this wouldn't work because
all the remaining characters in the file would need to
"slide over" to accommodate the change in length. Such
things can be done, but they are not easy. Two other
possibilities:

- Instead of trying to update the file "in place,"
consider reading the old file and writing a new
one with updated information. Just copy data from
the old file to the new, but whenever you recognize
a line that you want to change, write out the new
version instead of the old. This technique works
best if you can "batch" many changes together and
do them all in one pass over the data.

- If the order of lines in the file is not important,
you can "replace" a short line with a longer one
by (1) marking the original as "ignore me" by
changing its first character to 'x' or something
else that can't occur in valid data, and (2) writing
the new version of the line at the end of the file.
When reading the file in some other program, ignore
any line that begins with 'x'.

There are fancier schemes, too, but I can't tell from
your description whether they'd be worth while.
Thank you for an honest answer.

I always lie.
 
E

Emmanuel Delahaye

Martin Svensson wrote on 11/08/04 :
I have a program that writes an IP address two control numbers and a date to
file, on one line. It's a basic text file and it looks like this:

----- beginning of file -----
192.168.0.1 0 0 2004-08-01
192.168.0.2 1 0 2004-08-21
192.168.0.4 0 1 2004-08-12
-------- end of file --------

I know how to write data to a file. But what if I want to change data in this
file, for instance, on line two I want to change the first control number to
a 0 instead of a 1. How would I do this?

Thank you for an honest answer.

I'm not sure what an 'honest' answer is, but here is mine:

- The brute force: Use a text editor. Period.

- The C-force: you need two files. One on read text mode, one on write
text mode. You read the original, line by line. You check the line and
copy them unchanged or not according to your will. he line being just
another array of char, replacing a character by another one is trivial.

Of course, you need the FILE functions declared in <stdio.h> (fopen(),
fgets(), fputs(), fclose() etc.).

Then you can smartly use rename() and remove() to get a new file with
the old name, and eventually the n-1 version of the file for undo (.bak
or whatever).
 
M

Martin Svensson

Thank you very much, it worked just fine. I need to figure out what
method I will use, read from one file and write to another or have the
whole data in one file and just replace characters. Let's say I have all
the data in one file. For example a whole IP scoop in the same format as
my first example. How do I search the file for let's say and IP address
and find out what line number it's at? And how do I go to that line
before I'll write data to the file? I can't find such information in the
man files for fseek or any other file function.

Help is much appriciated!
Thank you once again for the great example!

Martin
 
J

Jens.Toerring

Martin Svensson said:
Thank you very much, it worked just fine. I need to figure out what
method I will use, read from one file and write to another or have the
whole data in one file and just replace characters. Let's say I have all

Well, Eric Sosman pointed out that you can also "insert" into a
file (but typically it's not trivial and simply writing to a new
file and then replacing the old one with it tends to be simpler).
the data in one file. For example a whole IP scoop in the same format as
my first example. How do I search the file for let's say and IP address
and find out what line number it's at? And how do I go to that line
before I'll write data to the file? I can't find such information in the
man files for fseek or any other file function.

You will probably have to do that manually, i.e. reading in lines,
counting them and the number of characters in them and use string
comparison functions to find out if the IP address you're looking
for is on that line. Assuming no further complications (i.e. lines
that are longer than the buffer you use for reading in lines) some-
thing like the following should do the trick (but take care, it's
completely untested):

#define MAX_LINE_LEN 4096 /* must be longer than longest input line! */

int ip_replace( FILE *fp, const char* old_ip, const char *new_ip )
{
long cur_pos = 0;
char buf[ MAX_LINE_LEN ];
char *where;

if ( strlen( old_ip ) != strlen( new_ip ) ) /* can we replace? */
return 1;
rewind( fp );
while ( fgets( buf, MAX_LINE_LEN, fp ) != NULL ) {
if ( ( where = strstr( buf, old_ip ) ) == NULL ) {
cur_pos += strlen( buf );
continue;
}
if ( fseek( fp, cur_pos + where - buf, SEEK_SET ) != 0 ||
fprintf( fp, "%s", new_ip ) != 1 )
break;
return 0;
}
return 1;
}

The function returns 0 if the replacement in the file of 'old_ip' by
'new_ip' was successful and 1 on all kinds of failures. I didn't
bother with line numbers here, but it's trivial to add a variable
for the line count and increment it after each successful fgets().

Regards, Jens
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,146
Messages
2,570,831
Members
47,374
Latest member
anuragag27

Latest Threads

Top