JC94
JC94

Reputation: 159

Writing a struct to a file in c

This is my code, where I read 256 bytes in "example.txt" and store it in chunk.payload.

I want to be able to first write my struct to "write.txt" then write the contents that I read to "write.txt". I was able to use fwriteto write everything in chunk.payload to the file, but I am having trouble writing the entire struct to the file.

#define MAXSIZE 256
int main(void){
    FILE *fp = fopen("C:\\Users\\alice\\Desktop\\example.txt", "r");
    FILE *wr = fopen("C:\\Users\\alice\\Desktop\\write.txt", "w+");

    struct packet{
      unsigned short block_num;
      unsigned short block_size;
      unsigned short crc;
      unsigned char *payload;
    };

    /*Create A dummy packet */
    struct packet chunk;
    chunk.block_num = 0;
    chunk.block_size = 256;
    chunk.crc = 0x101001;
    chunk.payload = malloc(MAXSIZE + 1);  // allocating memory
    chunk.payload[MAXSIZE] = '\0';

    //read first 256 lines and store into chunk.payload
    int read = fread(chunk.payload, sizeof(char), MAXSIZE, fp);  

    // Write struct to write.txt
    fwrite(&chunk, sizeof(chunk), 1, wr);

    // Write whatever has been read so far to write.txt
    fwrite(chunk.payload, sizeof(char), read, wr);

    getch();
    fclose(fp);
    fclose(wr);
    return 0;

The way I wrote my call:

fwrite(&chunk, sizeof(chunk), 1, wr);

actually allowed me to compile the code but I ended up having random symbols written to my file before the 256 bytes that i read were written to my file

What is the correct method to do this?

Upvotes: 3

Views: 4817

Answers (4)

jduck
jduck

Reputation: 109

Your chunk structure contains a pointer to the payload. These are the "junk" characters you're seeing. Since you're limiting the payload size to MAXSIZE anyway, you could just set payload to be statically sized instead:

struct packet{
  unsigned short block_num;
  unsigned short block_size;
  unsigned short crc;
  unsigned char payload[MAXSIZE];
};

This has the added advantage of not saving a pointer, using the heap, etc. In this situation your first fwrite will write the entire thing, including the payload and your second fwrite isn't needed.

If you need to have arbitrary sized payloads then you can use this old trick:

struct packet{
  unsigned short block_num;
  unsigned short block_size;
  unsigned short crc;
  unsigned char payload[0];
};

/*Create A dummy packet */
struct packet *chunk;
chunk = (struct packet *)malloc(sizeof(struct packet) + packetsize + 1);
chunk->block_num = 0;
chunk->block_size = 256;
chunk->crc = 0x101001;
chunk->payload[packetsize] = '\0';

Then you'd need to update your first fwrite to be:

// Write struct to write.txt
fwrite(chunk, sizeof(*chunk) + packetsize, 1, wr);

NOTE: You still don't need the second fwrite in this case.

Also, don't forget the add one for the NUL terminator if you want to save that too.

Upvotes: 0

mahendiran.b
mahendiran.b

Reputation: 1323

Payload is character datatype and other members of the structures are integer. You are creating text file. So, convert the integer to character and then write into write.txt

Like this also possible;

typedef struct Test
{
int a,b,c, d;
}Ref;

main () {

 fp=fopen("/home/test_prog/sampe.txt", "w+");
 sprintf (data, "%d %d %d %d", example.a, example.b, example.c, example.d);
 fwrite (data, sizeof(char), strlen(data) , fp  );
 fclose (fp);

}

Upvotes: 0

TonyWilk
TonyWilk

Reputation: 1477

Your first fwrite is attempting to write the binary contents of the packet structure to your write.txt file:

// Write struct to write.txt
fwrite(&chunk, sizeof(chunk), 1, wr); 

The second:

// Write whatever has been read so far to write.txt
fwrite(chunk.payload, sizeof(char), read, wr); 

is writing the content of your malloc'd payload. I don't think you want to write the binary to the file. If you want to write packet struct values as text to the file before the payload, you will have to do something like fprintf them one by one e.g.

// write contents of 'chunk' to text file
fprintf( wr, "block_num= %d\n", chunk.block_num );
...
fwrite(chunk.payload, sizeof(char), read, wr);

also note that your payload text will not be properly zero-terminated if read is less than MAXSIZE.

Upvotes: 1

ooga
ooga

Reputation: 15511

fread and fwrite are generally for reading/writing binary data. You want to write text data, which is usually done with fscanf or fgets for input, and fprintf for output.

Upvotes: 0

Related Questions