ifstream file I/O and strings or structs

This is a discussion on ifstream file I/O and strings or structs within the C++ Programming forums, part of the General Programming Boards category; Hello, I am looking for an efficient C++ technique for writing a data structure to a file and retrieving it ...

  1. #1
    Registered User
    Join Date
    Jan 2006
    Posts
    6

    ifstream file I/O and strings or structs

    Hello,
    I am looking for an efficient C++ technique for writing a data structure to a file and retrieving it later. To write the file, I've been doing the awkward thing of copying all my integer variables of the displayPacket class into a string class and writing it out to an ostream class with <<. For the input, I am using ifstream, but the compiler won't accept any data types besides the most basic (integer, etc).

    Any suggestions?
    Frank

    Code:
    	if(strcmp( (char *)myString, "save")==0)
    	{
    		ofstream myFile("filename.dat" );
    
    		myFile<< displayPacket.params;
    		myFile<< displayPacket.payload;
    
    		myFile.close();
    	}
    
    
    	if(strcmp( (char *)myString, "open")==0)
    	{
    		ifstream myFile("filename.dat" );
    
    		myFile >> displayPacket.params; /*compile error: the stream does not like the string class*/
    		myFile >> displayPacket.payload; /*compile error: the stream does not like the string class*/
    
    	       myFile >> i;	/*Works for integer i*/
    
    		myFile.close;
    Last edited by Ken Fitlike; 09-16-2006 at 12:05 PM. Reason: added code tags

  2. #2
    and the hat of wrongness Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    32,749
    Post some types with that lot, like how you declared various things.

    > strcmp( (char *)myString, "save")==0
    If you need a cast to make strcmp work, then you've done the wrong thing.
    If myString is a std::string type, then myString == "save" will do just fine.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.
    I support http://www.ukip.org/ as the first necessary step to a free Europe.

  3. #3
    Registered User
    Join Date
    Jan 2005
    Posts
    7,344
    >> compile error: the stream does not like the string class
    You have to #include <string>.

  4. #4
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,048
    Code:
    if(strcmp( (char *)myString, "open")==0)
    If you have to cast myString to get that to compile, you have a problem. BTW, strcmp is in <cstring>.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  5. #5
    Registered User
    Join Date
    Jan 2006
    Posts
    6
    Hi,
    Thanks for the input on the comparison with open and save. It was written a while ago when my undestanding was lesser for the string classs. My difficulties are with :
    <code>
    myFile >> displayPacket.params; /*compile error: the stream does not like the string class*/
    </code>
    In other words, how to input a data structure from an ifstream.

    Also, should I just work with fstream instrad of ifstream?

    Frank

  6. #6
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,048
    This isn't HTML, it's BBCode. [code] instead of <code>, and [/code] instead of </code>.

    In other words, how to input a data structure from an ifstream.
    You need to read in each member of the structure individually. A function is good for this (or a member function if the structure is in fact a class).

    Also, should I just work with fstream instrad of ifstream?
    No, since you'll never need to use output on the stream.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  7. #7
    Registered User
    Join Date
    Jan 2006
    Posts
    6
    I am trying to do something similar to this
    [URL="http://cboard.cprogramming.com/showthread.php?t=82638&highlight=ifstream"]
    where he is doing the input/output on a struct, while I am working on my packetClass
    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();
    }
    Now, if I would like to not use at all any pass by references as a prevention for all my programs.
    Now, if I do this which I don't like for the above reason:
    Code:
    if(strcmp( (char *)myString, "open")==0)
    {
    	ifstream myFile("filename.txt", ios_base::binary  );
    
    
    	myFile.read( (char *)&displayPacket.params , sizeof(displayPacket.params)  ); 
    	/*Don't want to to use pointers at all, thus avoiding risk of unitialized pointers*/
    	myFile.read( (char *)&displayPacket.payload, sizeof(displayPacket.payload) );
    	/*Don't want to to use pointers at all, thus avoiding risk of unitialized pointers*/
    
    	myFile.close();
    where my displayPacket is my own packet class and the params is a string class, the compiler complains that illegal use of sizeof() and illegal operation on bound member function ecpression.

    Isn't there a way to do myFile >> packet? Could I derive a class improvedifstream from the ifstream and make a function that will handle a pass by value of a string and do a file.read( buff, sizeof(buf) where I guarantee that buf is inside the class of improvedifstream? Somebody must have done this before and I'd be surprised that this sort of operation in not inside standard classes.
    Frank

  8. #8
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,796
    >Now, if I would like to not use at all any pass by references as a prevention for all my programs.
    Eh? Can you explain this in more detail?

    >where my displayPacket is my own packet class and the params is a string class
    Don't do that. Ever. You can't use istream::read or ostream::write on a non-trivial class. Those member functions pun the argument into an array of unsigned char and write it directly to a binary oriented file. However, non-trivial (ie. non-POD) classes can't portably be punned into an array of unsigned char. So at best trying to do it is non-portable, and at worst it's undefined behavior.

    What you want to do is provide a serialize and unserialize member function in your packet class that can turn the packets into strings which can then be safely written:
    Code:
    #include <cstdio>
    #include <cstring>
    #include <fstream>
    #include <iostream>
    
    class Packet {
    public:
        enum { PACK_SIZE = 10 };
    
        Packet(): thing_ ( 0 ) {}
        Packet ( int init ): thing_ ( init ) {}
    
        const char *Pack()
        {
            std::memset ( packed, '\0', PACK_SIZE );
            std::sprintf ( packed, "%d", thing_ );
    
            return packed;
        }
    
        const Packet& Unpack ( const char *p )
        {
            std::sscanf ( p, "%d", &thing_ );
    
            return *this;
        }
    
        friend std::ostream& operator<< ( std::ostream& out, const Packet& packet )
        {
            return out<< packet.thing_;
        }
    private:
        int thing_;
        char packed[PACK_SIZE];
    };
    
    int main()
    {
        std::ofstream out ( "test.dat", std::ios::binary );
    
        if ( out ) {
            for ( int i = 0; i < 10; i++ )
                out.write ( Packet ( i ).Pack(), Packet::PACK_SIZE );
    
            out.close();
        }
    
        std::ifstream in ( "test.dat", std::ios::binary );
    
        if ( in ) {
            Packet packet;
            char buf[Packet::PACK_SIZE];
    
            while ( in.read ( buf, Packet::PACK_SIZE ) )
                std::cout<< packet.Unpack ( buf ) <<'\n';
        }
    }
    >Isn't there a way to do myFile >> packet?
    Yes, just overload the operator>> for your class, much like I've overloaded operator<< in the code above.
    My best code is written with the delete key.

  9. #9
    Cat
    Cat is offline
    Registered User
    Join Date
    May 2003
    Posts
    1,571
    Quote Originally Posted by Prelude
    >where my displayPacket is my own packet class and the params is a string class
    Don't do that. Ever. You can't use istream::read or ostream::write on a non-trivial class. Those member functions pun the argument into an array of unsigned char and write it directly to a binary oriented file. However, non-trivial (ie. non-POD) classes can't portably be punned into an array of unsigned char. So at best trying to do it is non-portable, and at worst it's undefined behavior.
    Well, I do know that you can only use it on very limited classes (things that I would normally use structs for) but I do think it has a very useful purpose, when reading and writing binary records, where you know the size and contents of each field is fixed.
    You ever try a pink golf ball, Wally? Why, the wind shear on a pink ball alone can take the head clean off a 90 pound midget at 300 yards.

  10. #10
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,048
    But writing an object to a file that has pointers etc inside it is a bad idea, because when the object is restored those pointers will be pointing in vacuo.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  11. #11
    Cat
    Cat is offline
    Registered User
    Join Date
    May 2003
    Posts
    1,571
    Quote Originally Posted by dwks
    But writing an object to a file that has pointers etc inside it is a bad idea, because when the object is restored those pointers will be pointing in vacuo.
    Oh, absolutely.
    You ever try a pink golf ball, Wally? Why, the wind shear on a pink ball alone can take the head clean off a 90 pound midget at 300 yards.

  12. #12
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,796
    >where you know the size and contents of each field is fixed
    As long as the type has binary compatibility with C, you're fine. In other words, just about any useful class doesn't meet the requirements. Off the top of my head, an object of non-POD type cannot have:

    1) Any of the big three beyond the defaults (constructor, destructor, assignment operator)
    2) Private or protected members
    3) Reference members
    4) Non-POD members
    5) Virtual functions
    6) Base classes

    This has more to do than just the risk of shallow copying pointers.
    My best code is written with the delete key.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Need Help Fixing My C Program. Deals with File I/O
    By Matus in forum C Programming
    Replies: 7
    Last Post: 04-29-2008, 08:51 PM
  2. I/O with strings
    By kristentx in forum C++ Programming
    Replies: 1
    Last Post: 09-13-2007, 03:18 AM
  3. gcc link external library
    By spank in forum C Programming
    Replies: 6
    Last Post: 08-08-2007, 04:44 PM
  4. Replies: 3
    Last Post: 03-04-2005, 02:46 PM
  5. strings and file i/o
    By batgirl in forum C++ Programming
    Replies: 2
    Last Post: 09-24-2001, 03:20 AM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21