简体   繁体   中英

How to write a struct to a file using write() function?

I want to write a struct object to a file using the write() function. It has to be that function.

My input from terminal is: ./main.c output.dat John Doe 45

When I run the program and open the output.dat there are bunch of letters that don't make sense. Please help me.

The output I want in my output.dat file is: John Doe 45

My code:

struct Person{
  char* name;
  char* lastName;
  char* age;
};

int main(int argc, char** argv){

    struct Person human;
    /* get the argument values and store them into char*         */
    char* fileName = argv[1];
    char* name = argv[2];
    char* lastName = argv[3];
    char* age = argv[4];

    /* set the values of human object */
    human.name = name;
    human.lastName = lastName;
    human.age = age;

    /* open the file */
    int file = 0;
    file = open(fileName, O_RDWR); /* I want to have read&write set! */
    write(file, &human, sizeof(human));
    close(file);


    return 0;
}

When you write the struct, you only write the values in the struct itself. In your case, those values are pointers to other places in memory, not the string data. Thus, you end up writing three pointers worth of memory addresses (12 or 24 bytes on most systems) that aren't all that useful (since they apply to the memory space of the currently running program, which won't be the same on the next run).

You're going to need to design a more useful serialization format that actually writes out the contents of the strings, not their addresses. Options would include simple newline or NUL separated text, binary length prefixed text, or with third party libraries to get it right, CSV, JSON, or XML (if you're feeling ambitious, a database of some sort).

For example, with binary length prefixed text, you might do something like:

uint32_t len;

len = strlen(name);
write(file, &len, sizeof(len));
write(file, human.name, len);
len = strlen(lastName);
write(file, &len, sizeof(len));
write(file, human.lastName, len);
... repeat for age ...

which allows you to read it back in by reading each string length (fixed size), then using it to figure out how many bytes must be read to get the string.

You can't just write out the object. You need to write out each of the internal pointers individually.

Something like this:

file = open(fileName, O_RDWR); /* I want to have read&write set! */

write(file, human.name, std::strlen(human.name) + 1);
write(file, human.lastName, std::strlen(human.lastName) + 1);
write(file, human.age, std::strlen(human.age) + 1);

close(file);

Notice I add +1 to the length of the strings to make sure I also write out the terminating zero.

If you know the maximum length of each field, you can try making the fields an array. Remember to add 1 for null byte

struct Person{
  char name[32]; //31 char long + null 
  char lastName[32]; // 31 char long + null
  char age[4]; // 3 char long + null
};

Then your fwrite will work fine. But you need to strcpy the values in to the struct.

strlcpy(human.name, name, sizeof(human.name));

and so on for each field. strlcpy makes sure your string is null terminated.

Thanks to all, I sloved it like this. Although it is not ideal it gets the job done :) :

struct Person{
   char name[20];
   char lastName[20];
   char age[20];
};

int main(int argc, char** argv){

   struct Person human;
   /* get the argument values and store them into char*         */
   char* fileName = argv[1];
   char* name = argv[2];
   char* lastName = argv[3];
   char* age = argv[4];

   sprintf(human.name,name);
   sprintf(human.lastName,lastName);
   sprintf(human.age,age);

   /* open the file */
   int file = 0;
   file = open(fileName, O_RDWR); /* I want to have read&write set! */
   write(file, &human, sizeof(human));
   close(file);


   return 0;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM