#Writing a struct to file.

44 messages · Page 1 of 1 (latest)

long rivet
#

Guys, if I have a write function that writes a char *buf to a file (Intending to write byte by byte)

how can I pass a struct to it?

My goal is to be able to take the resulting file and read back the struct contents.

struct head{
        long headS;
        long pieceS;
        int nSplit;
};

the write function is straightforward just write() from unistd.h wrapped for some error checking and some lseek() action.

I was trying something like this. But is failing horribly.

writeFile((char *)header, PATH , HEADER_SIZE);

where header is a pointer to the struct.

Reading online I was seeing that I should just write each element on three write functions, but I figure what's the point of the struct then...

How would you do it?

dry mantleBOT
#

When your question is answered use !solved to mark the question as resolved.

Remember to ask specific questions, provide necessary details, and reduce your question to its simplest form. For tips on how to ask a good question use !howto ask.

shut flame
#

I would then consider writing the data into a JSON file using the prescribed function.

long rivet
#

No, sorry I don't think I'm explaining myself correctly. I'm writing bytes to a file. I have no use for a text based output.

bronze dirge
#

You might want to provide a bit more context. What 'is failing horribly' means exactly?

long rivet
#

Sorry sometimes making a good question is really hard, Intended to ask for general ideas. So I could get past my block.

so my struct is this one

struct head{
        long headS;
        long pieceS;
        int nSplit;
}header;

Values are initialized as

header->headS = pieceSize[0];
header->pieceS = pieceSize[1];
header->nSplit = nSplit;

The values themselves are

header->headS  // 182292
header->pieceS // 182266
header->nSplit // 10

And I call this function.

writeFile((char *)header, paths[i], 24, 0, 0);

This is the function iself

int writeFile(char *buf, const char *path, int itemN,
                int bufOffset, off_t seekOffset){

        int flags = O_WRONLY | O_CREAT | O_TRUNC;
        mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;

        //*****debug******
        off_t cur;
        //***************

        int fd = openFile(path, flags, mode);

        cur = lseek(fd, seekOffset, SEEK_SET);
        //*****debug******
        printf("Writing %s, offset: %ld\n", path, cur);
        //***************
        errno = 0;
        if((write(fd, buf + bufOffset, itemN)) != itemN){
                fprintf(stderr, "Error, Partial Write\n");
                return EXIT_FAILURE;
        }
        //*****debug******
        cur = lseek(fd, 0, SEEK_CUR);
        printf("Writing %s, offset: %ld\n", path, cur);
        printf("-------\n");
        //***************

        if(errno != 0 ){
                perror("Failed writing to file\n");
                return EXIT_FAILURE;
        }

        close(fd);
        return EXIT_SUCCESS;
}

when I look at the resulting file I see this.

hexdump -C piece1
00000000  14 c8 02 00 00 00 00 00  fa c7 02 00 00 00 00 00  |................|
00000010  0a 00 00 00 00 00 00 00                           |........|
00000018

Which is not what I'm expecting.

long rivet
#

the process output says

headS: 182292|pieceS: 182266|nSplit 10

Writing ./piece1, offset: 0
Writing ./piece1, offset: 24
-------
-rw-rw-r-- 1 spike spike 24 Jun 16 13:23 piece1
#

...I think I Just failed at reading hex

long rivet
#

Oh god is true... I was getting the right data I just failed at reading HEX.

02c814
0 + 131072 + 49152 + 2048 + 16 + 4 =  182292

02c7fa
0 + 131072 + 49152 + 1792 + 240 + 10 =  182266

0a
10 = 10
#

Well, this is solved. Thanks guys!
The problem was ME☀️

dry mantleBOT
#

@long rivet Has your question been resolved? If so, type !solved :)

long rivet
#

!solved

dry mantleBOT
#

Thank you and let us know if you have any more questions!

This thread is now set to auto-hide after an hour of inactivity

bronze dirge
#

Glad you managed to figure it out. Do note that writing structs into a file that way (i.e. without serialization of sort) is generally discouraged. This may cause portability issues accross systems

long rivet
#

@bronze dirge thanks ! what would be an alternative?
I'm self studying so I really have no mentor to teach me best practices.

#

I thought I was doing serialization lol

bronze dirge
#

Serialization of sort. One can write the members of the structs themselves (without padding who may present), or better yet, one can write those members as strings

long rivet
#

what could really vary across systems?
I think you mean my implication that two longs and an int will always be 24 bytes? with the padding

bronze dirge
#

The problem here is that writing say numbers in they binary form may or may not be compatible with other systems (due to endianess)

long rivet
#

"(due to endianess) "ahh I had to read that term while trying to figure out how to read the HEX.
I haven't really learned a lot about it.

bronze dirge
long rivet
#

I wonder how filetypes handle it.

Like a png image, I figure must have some metadata on its first bytes so you know is a png.

bronze dirge
long rivet
#

much simpler though. just header + data

bronze dirge
long rivet
#

I'm enjoying the conversation, thank you!
What do you mean multiple bytes at the time?

I can see it for the "content data" portion, but what about the headers and Identifiers, those are similar to mine no? some custom datatype (Structure like)

#

I guess, what makes a general well known portable filetype different from my attempt?

bronze dirge
#

'multiple bytes at a time' refers to any (primitive) object who's size is larger than a byte.

Lets for example consider the short 1. On big endian systems it may be represented as 0x001 on little endian systems however, the same number will be represented as 0x0100

#

On the other hand a char with the value of 1 will be represented as 0x01 on either system

long rivet
#

right because it cannot be changed by the endian is "atomic"

bronze dirge
bronze dirge
long rivet
#

that would allow for an unknown system to work with a filetype that was never engineered to be read on it.

bronze dirge
#

All files created on a certain type of system is only compatible with the same system

long rivet
#

I'm giving too much thought to it really I believe.. I'm honestly far from thinking about portability in my learning.

#

but is a great thought exercise.

#

I do need to sprinkle those "good decisions" on code so I grow acustomed to it.

bronze dirge
#

Thats fair. Just wanted to raise the subjetc. You don't need to really consider it at this stage

long rivet
#

I'm almost done with this project of mine 🙂 now with a "header" saved on the first file piece, I should be able to move into making a merge function
which would read the first file and iterate through all the pieces and merge them as a single file. (hopefully)

#

I'm pretty much spliting an image in N pieces and challenging myself to see if I can merge it again. Simple concept I suppose, but I'm learning a lot

#

I will fight to muster up the courage to get it into code review once done 😁