Thread: Writing a struct to a binary file

  1. #1
    Registered User
    Join Date
    Oct 2005
    Location
    Brasil
    Posts
    220

    Writing a struct to a binary file

    Code:
    #ifndef _FILE_H_
    
    #define _FILE_H_
    
    #include "main.h"
    #include <fstream>
    
    using namespace std;
    
    struct MusicRecord
    {
    	char * Artist;
    	char * Album;
    	char * Title;
    	long size;
    	std::basic_string<WCHAR> Path;
    };
    
    class FileSystem
    {
    private:
    	ofstream Create;
    public:
    	FileSystem(void);
    	~FileSystem(void);
    
    	void ALP_InsertRecord( MusicRecord Rec, int Index );
    	void ALP_GetRecord( MusicRecord &Rec, int Index );
    };
    
    #endif
    
    ....
    
    
    #include "FileSystem.h"
    
    FileSystem::FileSystem(void)
    {
    }
    
    FileSystem::~FileSystem(void)
    {
    }
    
    void FileSystem::ALP_InsertRecord(MusicRecord Rec, int Index)
    {
    	fstream Stream( "playlist.alp", ios::out|ios::binary|ios::app);
    	Stream.seekp( ( Index ) * sizeof ( MusicRecord ) );
    	Stream.write( (char*) &Rec, sizeof( MusicRecord ) );
    	Stream.close();
    }
    
    void FileSystem::ALP_GetRecord(MusicRecord &Rec, int Index)
    {
    	fstream Stream( "playlist.alp", ios::binary|ios::in );
    	Stream.seekg( ( Index ) * sizeof( MusicRecord ) );
    	Stream.read( (char *) &Rec, sizeof( MusicRecord ) );
    	Stream.close();
    }
    
    ......
    
    	MusicRecord Rec;
    
    	Rec.Album = mp3fi.szAlbum;
    	Rec.Artist = mp3fi.szArtist;
    	Rec.Path = FilePath;
    	Rec.Title = mp3fi.szTitle;
    
    	FileSystem File;
    	Rec.size = sizeof(Rec);
    	File.ALP_InsertRecord( Rec, ItemCount );
    It simply isn΄t working any ideas?

  2. #2
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    Neither the char* members, nor the basic_string member can be written that way. Both store their data somewhere other than directly inside the struct (at least that's how basic_string usually does it).

    You can use fixed size character arrays if you want, like char Artist[20]. You can also put a little more effort into the insert and get functions and write out the size of each string first, followed by the string data, then read in the size of the string when getting so that you can create the correct amount of memory. If you did that, you should consider using string or wstring for all your needs.

  3. #3
    Registered User
    Join Date
    Oct 2005
    Location
    Brasil
    Posts
    220
    Code:
    struct MusicRecord
    {
    	string Artist;
    	string Album;
    	string Title;
    	string Path;
    };
    
    ...
    
    void FileSystem::ALP_InsertRecord(MusicRecord &Rec, int Index)
    {
    	ofstream Stream( "playlist.dat", ios::out|ios::binary|ios::app);
    	Stream.seekp( ( Index ) * sizeof ( MusicRecord ) );
    	Stream.write( (char*) &Rec, sizeof( MusicRecord ) );
    	Stream.close();
    }
    
    void FileSystem::ALP_GetRecord(MusicRecord &Rec, int Index)
    {
    	ifstream Stream( "playlist.dat", ios::binary|ios::in );
    	Stream.seekg( ( Index ) * sizeof( MusicRecord ) );
    	Stream.read( (char *) &Rec, sizeof( MusicRecord ) );
    	Stream.close();
    }
    Ok, its now this way.
    1)How can i just write the size of the string before it if i am using seekp and seekg?


    2)How do i allocate a memory to a string? i tought i could only add the things to it without having the same problem as char*.

    3)I think this code is correct but the file "playlist.dat" is full of unknown characters, just the small strings are written to it properly, the big ones are just something weird, so some records are correct and others are like "ΜΜΜ̈†7 ΜΜΜΜΜΜΜΜΜΜΜΜe o".

    Thank you

  4. #4
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    string is the same as basic_string, so what I said about char * and basic_string in the previous post applies to string. You can't do it that way because the string class stores its information outside of its own place in memory.

    The trick with writing the size of the string means that seekg and seekp won't work, because the size of each record will depend on the size of the string. If you want to use seekp/seekg, you will have to choose a maximum size for your strings and use that (in which case character arrays would be better).

    This is all assuming you need to write the file as records in binary for some reason. In many cases this isn't necessary, you can just write out the records in a specific format in regular text mode. Then, you'd load all records into a data structure and look them up by index in that.

  5. #5
    Registered User
    Join Date
    Oct 2005
    Location
    Brasil
    Posts
    220
    Any example on how i would do without using binary format?

  6. #6
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    Just use regular stream output. Separate each member with a delimiter. Separate each record by a newline. With string members it is a bit more complicated since the strings themselves might have the delimiter or newlines embedded within them. If that can happen, you could place them in quotes (and double up any quotes inside the string).

    Then, when you read it back in, you just read each quoted value one at a time and store it in your record, saving each filled record to a data structure like a vector. I don't have any specific examples, but it is a common technique.

  7. #7
    Registered User
    Join Date
    Mar 2006
    Posts
    725
    This *might* be overkill, but you could also link to some XML library and write all your class data in XML
    Code:
    #include <stdio.h>
    
    void J(char*a){int f,i=0,c='1';for(;a[i]!='0';++i)if(i==81){
    puts(a);return;}for(;c<='9';++c){for(f=0;f<9;++f)if(a[i-i%27+i%9
    /3*3+f/3*9+f%3]==c||a[i%9+f*9]==c||a[i-i%9+f]==c)goto e;a[i]=c;J(a);a[i]
    ='0';e:;}}int main(int c,char**v){int t=0;if(c>1){for(;v[1][
    t];++t);if(t==81){J(v[1]);return 0;}}puts("sudoku [0-9]{81}");return 1;}

  8. #8
    Registered User
    Join Date
    Oct 2005
    Location
    Brasil
    Posts
    220
    I think XML is a good choice. Any resource on how to use XML?

  9. #9
    Registered User
    Join Date
    Mar 2006
    Posts
    725
    I was being satirical. Whatever you want, though. There are a lot of C++ libraries implementing XML parsers and readers you can use for free. The W3C should be a good starting point; however I wouldn't recommend XML for small, simple projects.
    Code:
    #include <stdio.h>
    
    void J(char*a){int f,i=0,c='1';for(;a[i]!='0';++i)if(i==81){
    puts(a);return;}for(;c<='9';++c){for(f=0;f<9;++f)if(a[i-i%27+i%9
    /3*3+f/3*9+f%3]==c||a[i%9+f*9]==c||a[i-i%9+f]==c)goto e;a[i]=c;J(a);a[i]
    ='0';e:;}}int main(int c,char**v){int t=0;if(c>1){for(;v[1][
    t];++t);if(t==81){J(v[1]);return 0;}}puts("sudoku [0-9]{81}");return 1;}

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Converting from C to C++
    By Taka in forum C++ Programming
    Replies: 5
    Last Post: 04-08-2009, 02:16 AM
  2. Trouble writing to file using fwrite()
    By yougene in forum C Programming
    Replies: 4
    Last Post: 12-30-2008, 05:13 PM
  3. Replies: 2
    Last Post: 05-09-2008, 07:27 AM
  4. Replies: 16
    Last Post: 10-29-2006, 05:04 AM
  5. simulate Grep command in Unix using C
    By laxmi in forum C Programming
    Replies: 6
    Last Post: 05-10-2002, 04:10 PM