Link to home
Start Free TrialLog in
Avatar of nsanga
nsanga

asked on

How do I add a character into the header file?

Hi experts,
We have a file format, in which we are writing the format version in the header along with some other information. Initially some information is written into the file then followed by the version information. After that, the file data will be written. Now the version is "4.0.2". I would like to introduce a flag in the version for a specific task. In other words, I would like to read the file and if it is "4.0.2", then I would like to make it "4.0.3" or "4.0.2A"

How do I do it without disturbing the file format.

Warm Regards,
Narahari Sanga
Avatar of Narendra Kumar S S
Narendra Kumar S S
Flag of India image

The flat file is a sequential storage and you can not push or delete the data in a file. The only possibility is overwriting!
So, the best way to achive your objective is to read all the contents into a character buffer, close the file and do all the modifications in this buffer itself. After this, open the file again, this time in write mode and write back the buffer to the file and close it.

Hope this works for you....

-Narendra
if u are not worried about doing it programmatically .. then   u can get an easy search/replace script with sed/awk or perl ..
btw what OS u working on
Avatar of Kocil
Kocil

to change from 4.0.2 to 4.0.3 is easy,
but not from 4.0.2 to 4.0.2A because it needs 1 more byte => you have to shift the entire file.

This is for the first case.

// assume this is your header
typedef struct {
   char info[100];
   char version[5];
   char other[100]
} THeader;

change(char *fname, char *old, char *new)
{
   static THeader buffer;
   FILE* f=fopen(fname, "w");
   char *pos;
   fread(f, buffer);
   if (strncmp(buffer.version,old,5) == 0) {
      strcpy(buffer.version, new);
      fseek(f,0);
      fwrite(f,buffer);
   }
}

   
main()
{
   change("MyFile", "4.0.2", "4.0.3");
}

Ooops, correction.

change(char *fname, char *old, char *new)
{
  static THeader buffer;
  FILE* f=fopen(fname, "rw");
  fread(buffer, sizeof(THeader), 1, f);
  if (memcmp(buffer.version,old,5) == 0) {
     memcpy(buffer.version, new, 5);
     fseek(f,0,SEEK_SET);
     fwrite(buffer, sizeof(THeader), 1, f);
  }
}

Sorry, no manual inside :)
Avatar of nsanga

ASKER

Kocil,
Thanks for your suggestion. I will try to implement as you suggested. However, I would like bring some thing into your notice that the data is written in the binary format. Each element is written with the type (as you mentioned in the example, the version will have some type and the number of words to store the version information. This is to read those many bytes for the version and also a flag for internal use).

I assume that I need to open the file in "rwb" mode. Please let me know. I tried this method some time back and couldnot write successfully into the file.

ssnkumar,
Thanks for the info. However, I may not go ahead with this method as there will be lots of data after the header, which requires me to read the entire file and store the information.

Warm regards,
Narahari Sanga
Let me hope that your version information takes 5 charaters, sice you have written 4.0.2. Now you want to change the version information without altering the file format, now it may contaion 6 charaters also.

One solution to overcome this problem is to assign a file pointer at that place instead of the version number. The file pointer will indicate the place where the version is stored. I suggest you to store the version informationin the end of the file. In this way you are not going to alter the file format. If you have already written some code to write or read the file, yhen you have to do a little modification there ( not that much ).

Another suggestion is that whenever you design a new file format always consider the future extension of that file. This is very important, that you may realize now.

I am a person working in the field of image processing, and this type of file format designing always comes in our work. If you want further help you can mail me in my personal email id [edited by moderator Mindphaser]. If you want help in this format itself then please specify the file format type, like image file, database file, etc.

Thank you

Hope this may help you.
>If you want further help you can mail me in my personal email id [edited by moderator Mindphaser].

I am seeing the same comment for 2nd time. Why are you asking them to contact you on your mail id!? Why don't you discuss the answer here itself, so that we also can know the answer...:-)
I don't see any reason for giving your mail ids to questioners and asking them to contact you. You can get the complete code here itself and this forum is open to discussions of any length.....
Please clarify....

-Narendra
Avatar of nsanga

ASKER

rajeev_devin,
Thanks for the suggestions regarding the format designing. I am working on a legacy product, which is started around 14 years back.

Coming to the solution, I may not go for adding a pointer since we have delivered many versions to the customers and the older versions of the software don't understand the modified format.

Narendra,
I am thinking of reading the entire file (ofcourse, it is a costly operation for me) and writing the contents back with the modified format number.

Experts,
Please suggest a possible solution, if I would like to fix the version number to same number of bytes (e.g. "4.0.3")  

Warm regards,
Narahari Sanga
Still I am in a confused state... as to what you are actually doing!?:-))
Are you trying:
To change the version number written inside a file?
Or Creating a new file with new version number?

-Narendra
i hope u know the location of this particular string.. as  u say u know the format of the file .. formatting means fixing/knowing the location of various elements
and
also if u want to keep the number of bytes same
what if ur existing version is 4.0.9 .. wud u like it to be
4.1.0 OR 4.0.10 ( in this case number of bytes increased)

what if its 9.9.9 ?

also
to make 4.0.2 to 4.0.3 its pretty easy
char *idx = location of start of "4.0.2" in the big string of file loaded in the memory.

now to make this 4.0.3 just have to do

(*(idx+4))++;
this will make 4.0.2 to 4.0.3

but dont forget about the cases that i said above..
other wise u can do is
int len=strlen("4.0.2");
char * temp=(char*)malloc(len);

memcpy(temp,idx,len);
now process the "4.0.2" string in the temp in the way u wish
and then when u change 'temp' to "4.0.2" OR "4.1.0" IN case of 4.0.9
move the bytes back to main string
memcpy(idx,temp,len);

its that simple .. its really isnt much of a problem..
 if u can show that part of ur file(from start to 4.0.2) ... i can be more precise and give more generic solution


Avatar of nsanga

ASKER

Narendra,
My intention is to change the value of a field in the header from "4.0.2" to "4.0.3" in the file. I have opened the file in "rwb" mode and read the header till the version number and tried to write "4.0.3". However, it did fail.

Now, I am thinking to read the file (consists of header and "n" number of elements information) and close the file. Then, I will reopen the file and dump everuthing with the modified version number in the header i.e., "4.0.3"

I would like to do this because, I need to apply a different set of conversion routines if a file has "4.0.3" as the version number.

Hope, it is clear now.

Warm regards,
Narahari Sanga
I tried this problem in my C code as follows:
1. First I have written the version information in a test file.

FILE *fpt = fopen("test.dat","w+b");
char ver[] = "4.0.2";
fwrite(ver,1,5,fpt);
fclose(fpt);

2. With another program I first read the version to check out the old version number, replaced it with the new version number, and then again read the version number for verification. It is working fine.

/* Write version and data */
     char ver[6];
     FILE *fpt = fopen("test.dat","r+b");

     fread(ver,1,5,fpt);
     ver[5] = '\0';
     printf("%s",ver);

     fseek(fpt,0,SEEK_SET);
     strcpy(ver,"4.0.3");
     fwrite(ver,1,5,fpt);

     fseek(fpt,0,SEEK_SET);

     fread(ver,1,5,fpt);
     ver[5] = '\0';
     printf("%s",ver);



Hope this time it may help you.
Regards
Avatar of nsanga

ASKER

Rajeev,
Thanks for the suggestions and the code. I will try this and let you know.

My case is follows

1. As you have mentioned in Step 1

FILE *fpt = fopen("test.dat","w+b");
char ver[] = "4.0.2";
// write some long variables
// write a string
fwrite(ver,1,5,fpt);
// write some other data
fclose(fpt);

2. Now, I need to traverse till the version number and write "4.0.3"

Warm regards,
Narahari Sanga

I think that's simple if length of version number is fixed.
>I have opened the file in "rwb" mode and read the header till the version number.
If you are sure that you have read till version number and after that you have "4.0.2" (or something like that). Then overwriting that with "4.0.3" must work!
I have got a sample program for you here...Try this (there are two files 1.c and 1.txt, both I have produced below. Do try them and give feedback. I am sure they will work for you):

// file 1.c
#include <stdio.h>

main()
{
    FILE *fp;
    char *str = (char *)malloc(25);
    char c;

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

    bzero(str, 25);
    fscanf(fp, "%s", str);
    fscanf(fp, "%s", str);
    fscanf(fp, "%c", &c);

    fprintf(fp, "4.0.3");

    fclose(fp);

    free(str);
}

The sample text file - 1.txt:

Version number 4.0.2 abcdefg
This is the next line
Please explain me if the 'long variables', you have written, is fixed or not. what is its' size. if not is there any delimiter. Then I can try out another code for you.
rajeev_devin

As ssnkumar already pointed out, we stronlgy discourage the use of email discussions here. Our policy is to keep discussions in this forum, so other askers can profit from it. That's what EE is all about, sharing knowledge and information.

I edited all the places where your email address showed up in this thread ....

** Mindphaser - Community Support Moderator **
Ooops, correction AGAIN.
This time it will work. Swear !
Last time I forgot to close the file :)

change(char *fname, char *old, char *new)
{
 static THeader buffer;
 FILE* f=fopen(fname, "rw");
 fread(buffer, sizeof(THeader), 1, f);
 if (memcmp(buffer.version,old,5) == 0) {
    memcpy(buffer.version, new, 5);
    fseek(f,0,SEEK_SET);
    fwrite(buffer, sizeof(THeader), 1, f);
    /* add this */
    fseek(f,0,SEEK_END);
    fclose(f);
 }
}
Damn ... BUG again.
I should not answer question near sleep time.

change(char *fname, char *old, char *new)
{
  static THeader buffer;
  FILE* f=fopen(fname, "rwb");
  fread(buffer, sizeof(THeader), 1, f);
  if (memcmp(buffer.version,old,5) == 0) {
    memcpy(buffer.version, new, 5);
    fseek(f,0,SEEK_SET);
    fwrite(buffer, sizeof(THeader), 1, f);
  }
  /* move to here */
  fseek(f,0,SEEK_END);
  fclose(f);
}
nsanga,
did you try out my sample program? Did it work? Any feedback/comments will help me to analyze furthur if needed....:-)

-Narendra
Avatar of nsanga

ASKER

Narendar,
I have tried your code. It's not writing "4.0.3" into the file.

rajeev_devin.
We are converting the long variable into an equivalent string and writing into the file.

Kocil,
This approach may not work since we are writing a long variable by converting into a string. Also, the number of bytes is also written into the file. The size of the header doesn't exactly read the header since the size of long variables is written into the file as a part of the header.

Warm regards,
Narahari Sanga
untill and unless you don't elaborate on your header information, and size, its' really impossible for me to try out anything. Try to elaborate.

regards
ASKER CERTIFIED SOLUTION
Avatar of Kocil
Kocil

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
>Narendar, I have tried your code. It's not riting "4.0.3" into the file.

I am surprised! I have tested the program on my system (Linux with gcc) and it's writing 4.0.3.
Is it writing something else or your 1.txt is not getting changed!?
I think the problem is with the file opening only! Try the following open statement:
fp = fopen("1.txt", "r+");

-Narendra
Avatar of nsanga

ASKER

Narendar,
I have created a sample application in VC to test your code (on WinNT system). I have tried the other file opening mode. The file 1.txt is still not changed.


Kocil,
Thank you so much. IT'S WORKING GREAT.

I have tried your code. (I just made a small change in the method "change"
from FILE* f=fopen(fname, "wb");
to FILE* f=fopen(fname, "r+wb");

Warm regards,
Narahari Sanga
Avatar of nsanga

ASKER

Thank you Kocil.

Since, the version number is written in the very beginning of the file. I feel, I can definitely go for this solution though this is not very fast as mentioned by Kocil.

Warm regards,
Narahari Sanga
You wellcome.