IZI_Shadow_IZI
IZI_Shadow_IZI

Reputation: 1931

C Program: How to properly use lseek() or fseek() to modify a certain part of a file?

I have a binary file in CSV format that contains multiple records. Each record is entered in as user_name, last_name, first_name, num_wins, num_losses, num_ties. I am creating a method to update a certain players record of wins,losses and ties. The user inputs the username to change followed by the changes to the wins, losses and ties. For example smithj 4 5 1. This will find the smithj record and add 4 to the wins etc.

How do I use lseek or fseek to accomplish this? Or is there another way to do this?

Upvotes: 1

Views: 8439

Answers (3)

Jonathan Leffler
Jonathan Leffler

Reputation: 753585

Response to request for write-up of example - assuming fixed size records:

enum { RECSIZE = 256 };

char buffer[RECSIZE];
FILE *fp = ...;   // File to read from and write to

int recnum = 37;  // Counting from record 0
long offset = recnum * RECSIZE;

if (fseek(fp, offset, SEEK_SET) != 0)
    ...error...
if (fread(buffer, sizeof(buffer), 1, fp) != 1)
    ...error...
...modify buffer...
if (fseek(fp, offset, SEEK_SET) != 0)
    ...error...
if (fwrite(buffer, sizeof(buffer), 1, fp) != 1)
    ...error...

Repeat the code from the declaration of recnum to the end once for each record that must be modified (think loop).

With variable size records that change size as you edit them, you have to work a lot harder - so much so that it is probably simpler to copy the old file into memory one record at a time, modifying the record appropriately, and then writing the modified record to a new file.

Upvotes: 1

jonescb
jonescb

Reputation: 22751

It's fairly easy to do if each record is the same number of bytes. You would check the first record to see if it's a match, and if not then do fseek(f, record_size, SEEK_CUR); and check the next record.

If each record is going to be a different number of bytes, all I can think of is that you put the number of bytes the record is before the actual record. And then read that in, and then fseek() that many bytes to get to the next record size. I've seen some binary file formats do this which makes things fairly easy.

Upvotes: 1

Steve Emmerson
Steve Emmerson

Reputation: 7832

Assuming the file is a text file, then you will have to pad the lines to a constant width. Then use lseek(), read(), and write() to modify the lines. Having a constant length for each line is crucial: it allows you to compute the starting position of each line.

Upvotes: 1

Related Questions