So I have an input.bin file which contains the following
IK-SZH;jdl72u;John Doe;2013-03-28 11:05
IK-GRR;kat91n;Jane Doe;2013-03-21 15:41
IK-GRR;oat62f;Jane Doe;2013-03-24 08:08
What I am doing is to read it into a struct. Doing some stuff with the data. Add/Delete lines.
Then i would like to write the content of the structure back to the input.bin file in the same format as above.
But instead of appearing as it is above. It's like this (no spaces):
IK-SZH NUL jdl72u NUL John Doe NUL NUL NUL NUL NUL 2013-03-28 NUL NUL NUL IK-GRR NUL kat91n NUL Jane Doe NUL NUL NUL NUL ...
When I re-read the file (with the NULs) It only puts the 1st line into the struct
My code
typedef struct foo {
char kid[7];
char jid[7];
char name[21];
char time[20];
} Foo;
Foo foo[200];
FILE* fp;
int size;
------- File reader
void read(char* filename){
fp = fopen(filename, "rb");
int i = 0;
while (!feof(fp)) {
if (fp==NULL){perror("File opening error\n"); exit(1);}
fscanf(fp,"%[^;]; %[^;]; %20[^\;]; %s\n", foo[i].kid, foo[i].jid,
foo[i].name, foo[i].time);
i++;
}
size = i;
print();
fclose(fp);
}
void print(){
int i;
for (i = 0; i < size; ++i){
printf("%s\t %s\t %s\t %s\n", foo[i].kid, foo[i].jid,
foo[i].name, foo[i].time);
}
}
----- Writer
void write(){
char str[1000];
FILE* f = fopen("input.bin", "wb");
fseek(f, 0, SEEK_SET);
int i;
for (i = 0; i < jel_size; i++)
fwrite(&foo[i], sizeof(struct foo), 1, f);
fclose(f);
}
Tried this, but this didn't write anything to the file:
char str[1000];
sprintf(str,"%s;%s;%s;%s\n", jelent[i].kazon,
jelent[i].jazon,jelent[i].nev, jelent[i].ido );
write(f,&str,sizeof(str))!=sizeof(str);
Your structure definition is:
typedef struct foo
{
char kid[7];
char jid[7];
char name[21];
char time[20];
} Foo;
The code that writes the structures to the file is in write()
:
for (i = 0; i < jel_size; i++)
fwrite(&foo[i], sizeof(struct foo), 1, f);
If the structures are intialized with all bytes zero, then for the first row of data you mention:
IK-SZH;jdl72u;John Doe;2013-03-28 11:05
we can infer that the structure contains:
IK-SZH\0
jdl72u\0
John Doe\0\0\0\0\0\0\0\0\0\0\0\0\0
2013-03-28 11:05\0\0\0\0
which more or less agrees with what you say the file contains:
IK-SZH NUL jdl72u NUL John Doe NUL NUL NUL NUL NUL 2013-03-28 NUL NUL NUL
By my reckoning, you're missing a few NULs after the name and the time and one NUL after the date.
If you want text output, you will have to format the data in write()
using fprintf()
analogous to the fscanf()
statement you have in the read()
function. You should probably return a status from the function to indicate whether it was successful. You can argue for checking that fclose()
was successful, too.
void write(void)
{
FILE *fp = fopen("input.bin", "w");
if (fp != 0)
{
for (int i = 0; i < jel_size; i++)
fprintf(fp, "%s;%s;%s;%s\n", foo[i].kid, foo[i].jid, foo[i].name, foo[i].time);
fclose(fp);
}
}
If you want binary output, you should use binary input in read()
. Again, you should consider returning an indication of success or failure; avoiding global variables is good, too.
void read(const char *filename)
{
FILE *fp = fopen(filename, "rb");
if (fp != 0)
{
for (i = 0; fread(&foo[i], sizeof(foo[i]), 1, fp) == 1; i++)
;
fclose(fp);
size = i;
}
}
Either technique will work; trying to use one on output and the other on input is going to lead to chaos and confusion.
Note that functions read()
and write()
are used by POSIX with a different interface. While you stick with Standard C, the names are fair for you to use, but you'd probably be better off with alternative names, such as reader()
and writer()
or foo_read()
and foo_write()
.
https://gist.github.com/anonymous/5288805
Changed code just a bit, commented, and also tested, so it works for sure.