strange read in of binary file

Discussion in 'C++' started by zl2k, Apr 11, 2008.

  1. zl2k

    zl2k Guest

    hi, there

    I have a appendable binary file of complex data structure named
    data.bin created by myself. It is written in the following format:

    number of Data, Data array

    Suppose I have following data.bin (3 Data appended to 2 Data):

    2, data0, data1, 3, data0, data1, data2

    When I read and display it, I always get the following output:

    2
    data0
    data1
    3
    data0
    data1
    data2
    3
    data with default value
    data with default value
    data with default value

    Why I get an extra data set with default values have the same number
    of Data as the previous valid one? Here is the read in code:

    ---------------------
    ifstream myfile2;
    myfile2.seekg(0);
    myfile2.open ("data.bin", ios::in | ios::binary);
    int *num2;
    while (myfile2.good()){
    myfile2.read((char*)num2, sizeof(int));
    cout<<*num2<<" "<<endl;
    Data *dataArray2 = new Data[*num2];
    myfile2.read ((char*)dataArray2, sizeof (Data) * *num2);
    //print dataArray2 content
    delete [] dataArray2;
    }
    myfile2.close();
    ---------------------

    Please help!

    zl2k
     
    zl2k, Apr 11, 2008
    #1
    1. Advertising

  2. zl2k

    zl2k Guest

    On Apr 11, 3:45 pm, "Victor Bazarov" <> wrote:
    > zl2k wrote:
    > > I have a appendable binary file of complex data structure named
    > > data.bin created by myself. It is written in the following format:

    >
    > > number of Data, Data array

    >
    > > Suppose I have following data.bin (3 Data appended to 2 Data):

    >
    > > 2, data0, data1, 3, data0, data1, data2

    >
    > > When I read and display it, I always get the following output:

    >
    > > 2
    > > data0
    > > data1
    > > 3
    > > data0
    > > data1
    > > data2
    > > 3
    > > data with default value
    > > data with default value
    > > data with default value

    >
    > > Why I get an extra data set with default values have the same number
    > > of Data as the previous valid one? Here is the read in code:

    >
    > > ---------------------
    > > ifstream myfile2;
    > > myfile2.seekg(0);
    > > myfile2.open ("data.bin", ios::in | ios::binary);
    > > int *num2;
    > > while (myfile2.good()){
    > > myfile2.read((char*)num2, sizeof(int));
    > > cout<<*num2<<" "<<endl;
    > > Data *dataArray2 = new Data[*num2];
    > > myfile2.read ((char*)dataArray2, sizeof (Data) * *num2);
    > > //print dataArray2 content
    > > delete [] dataArray2;
    > > }
    > > myfile2.close();
    > > ---------------------

    >
    > > Please help!

    >
    > Common mistake. First, you never check the result of your read
    > operations. Change your code to behave appropriately if the file
    > cannot be read (where you read your 'num2'): do you really want
    > to keep reading the stream if the first read fails? Second, I
    > strongly recommend reading the archives on file streams, 'read',
    > formatted (or unformatted) I/O, etc. BTW, what book are you
    > reading that doesn't explain how to handle input that can run
    > out of information (eof conditions)?
    >
    > V
    > --
    > Please remove capital 'A's when replying by e-mail
    > I do not respond to top-posted replies, please don't ask


    I tried while (!myfile2.eof()){} but makes no difference. How can I
    fix it? I know my code did not stop when reached the end of the file.
    zl2k
     
    zl2k, Apr 11, 2008
    #2
    1. Advertising

  3. zl2k

    zl2k Guest

    On Apr 11, 4:40 pm, "Victor Bazarov" <> wrote:
    > zl2k wrote:
    > > On Apr 11, 3:45 pm, "Victor Bazarov" <> wrote:
    > >> zl2k wrote:
    > >>> I have a appendable binary file of complex data structure named
    > >>> data.bin created by myself. It is written in the following format:

    >
    > >>> number of Data, Data array

    >
    > >>> Suppose I have following data.bin (3 Data appended to 2 Data):

    >
    > >>> 2, data0, data1, 3, data0, data1, data2

    >
    > >>> When I read and display it, I always get the following output:

    >
    > >>> 2
    > >>> data0
    > >>> data1
    > >>> 3
    > >>> data0
    > >>> data1
    > >>> data2
    > >>> 3
    > >>> data with default value
    > >>> data with default value
    > >>> data with default value

    >
    > >>> Why I get an extra data set with default values have the same number
    > >>> of Data as the previous valid one? Here is the read in code:

    >
    > >>> ---------------------
    > >>> ifstream myfile2;
    > >>> myfile2.seekg(0);
    > >>> myfile2.open ("data.bin", ios::in | ios::binary);
    > >>> int *num2;
    > >>> while (myfile2.good()){
    > >>> myfile2.read((char*)num2, sizeof(int));
    > >>> cout<<*num2<<" "<<endl;
    > >>> Data *dataArray2 = new Data[*num2];
    > >>> myfile2.read ((char*)dataArray2, sizeof (Data) * *num2);
    > >>> //print dataArray2 content
    > >>> delete [] dataArray2;
    > >>> }
    > >>> myfile2.close();
    > >>> ---------------------

    >
    > >>> Please help!

    >
    > >> Common mistake. First, you never check the result of your read
    > >> operations. Change your code to behave appropriately if the file
    > >> cannot be read (where you read your 'num2'): do you really want
    > >> to keep reading the stream if the first read fails? Second, I
    > >> strongly recommend reading the archives on file streams, 'read',
    > >> formatted (or unformatted) I/O, etc. BTW, what book are you
    > >> reading that doesn't explain how to handle input that can run
    > >> out of information (eof conditions)?

    >
    > >> V
    > >> --
    > >> Please remove capital 'A's when replying by e-mail
    > >> I do not respond to top-posted replies, please don't ask

    >
    > > I tried while (!myfile2.eof()){} but makes no difference. How can I
    > > fix it? I know my code did not stop when reached the end of the file.
    > > zl2k

    >
    > Look at what 'read' returns. You can also check the condition of the
    > stream right after 'read' to see whether the stream is "good". You
    > can check for 'eof' instead of "good" after 'read'...
    >
    > I don't want to write your program for you. Trust me, you'll be much
    > better off if you research this stuff yourself.
    >
    > V
    > --
    > Please remove capital 'A's when replying by e-mail
    > I do not respond to top-posted replies, please don't ask


    Thanks, I can jump out off the loop by checking the good() or eof()
    after myfile2.read((char*)num2, sizeof(int));
    So I can move one. Have good weekend.
    zl2k
     
    zl2k, Apr 11, 2008
    #3
  4. zl2k

    James Kanze Guest

    On 11 avr, 20:37, zl2k <> wrote:

    > I have a appendable binary file of complex data structure
    > named data.bin created by myself. It is written in the
    > following format:


    > number of Data, Data array


    Which doesn't begin to tell me anything about the format, at
    least if it is binary. You have to specify the format of the
    various types.

    > Suppose I have following data.bin (3 Data appended to 2 Data):


    > 2, data0, data1, 3, data0, data1, data2


    OK, but that's text.

    > When I read and display it, I always get the following output:


    > 2
    > data0
    > data1
    > 3
    > data0
    > data1
    > data2
    > 3
    > data with default value
    > data with default value
    > data with default value


    > Why I get an extra data set with default values have the same number
    > of Data as the previous valid one?


    The simple answer is that you've got so much undefined behavior
    in your code that we can't say anything about it. In practice,
    I find it hard to believe that the code didn't crash.

    > Here is the read in code:


    > ---------------------
    > ifstream myfile2;
    > myfile2.seekg(0);


    You can't seek on an unopened file. This should fail.
    According to the current standard, that means that all following
    operations should also fail (but I think a lot of
    implementations do reset the failbit on open, which is logical,
    and will be what the next version of the standard requires, I
    think).

    > myfile2.open ("data.bin", ios::in | ios::binary);


    Of course, you really should check that the open succeeded.

    > int *num2;


    Which points where? Avoid uninitialized variables, especially
    if they're pointers.

    > while (myfile2.good()){


    Classical error. At this point, good() doesn't tell you
    anything. (The standards committee would do well to deprecate
    the function. I've never found a use for it.)

    What you want is:

    while ( myfile.someInput... ) {

    > myfile2.read((char*)num2, sizeof(int));


    And bang. You pass an uninitialized pointer to istream::read().
    istream::read() isn't going to like that. Formally, it's
    undefined behavior, and no matter what the compiler and the
    library do after is correct. In a good implementation, unless
    you've turned off all debugging and turned on all optimization,
    it should crash the program.

    > cout<<*num2<<" "<<endl;


    Did the above read succeed? Who knows?

    > Data *dataArray2 = new Data[*num2];
    > myfile2.read ((char*)dataArray2, sizeof (Data) * *num2);
    > //print dataArray2 content
    > delete [] dataArray2;
    > }
    > myfile2.close();
    > ---------------------


    More information is needed. Like the actual format of the file.
    But the basic structure of the program should be something like:

    std::ifstream file( name, ios::in | ios::binary ) ;
    if ( ! file ) {
    // error, could not open...
    } else {
    readData( file ) ;
    }

    with

    void
    readData( std::istream& source )
    {
    int count ;
    if ( ! getInt( source, count ) ) {
    // error...
    } else {
    while ( someInput ) {
    // process input...
    }
    }
    }

    Reading and writing binary data requires some understanding of
    what you're doing, though. (Reading and writing text requires
    even more, but that's mostly been done for you.) I'd avoid it
    if at all possible.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
     
    James Kanze, Apr 12, 2008
    #4
  5. zl2k

    James Kanze Guest

    On 11 avr, 23:32, zl2k <> wrote:
    > On Apr 11, 4:40 pm, "Victor Bazarov" <> wrote:


    > Thanks, I can jump out off the loop by checking the good() or eof()
    > after myfile2.read((char*)num2, sizeof(int));


    As Victor said, research. Even a little research should reveal
    that good() is always the wrong function, and eof() is only
    really valid after you know that the input has failed.

    I think what Victor was getting at is that you should start by
    learning the error model used in iostream, and what the various
    state functions actually return. Their names are misleading, to
    put it mildly, and there is actually some ambiguity with regards
    to eof(), but there are standard idioms that are well
    documented, and that work.

    He also mentionned that you should research binary input, and
    how to implement binary formats. It's a non-trivial subject, to
    put it mildly, and best avoided until you understand some of the
    low level details of binary representation.

    And while he didn't mention it, I think you really have to learn
    at least a little about the C++ memory model, and what
    declarations mean, before you can even consider going further.
    Just defining a pointer doesn't create anything which it might
    point to, for example.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
     
    James Kanze, Apr 12, 2008
    #5
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Doug
    Replies:
    3
    Views:
    4,390
    Bruce Barker
    Nov 4, 2005
  2. Ron Eggler

    writing binary file (ios::binary)

    Ron Eggler, Apr 25, 2008, in forum: C++
    Replies:
    9
    Views:
    954
    James Kanze
    Apr 28, 2008
  3. Jim
    Replies:
    6
    Views:
    743
  4. Sniper Abandon
    Replies:
    3
    Views:
    243
    Robert Klemme
    Nov 19, 2009
  5. Alex Dowad
    Replies:
    4
    Views:
    285
    Michel Demazure
    May 1, 2010
Loading...

Share This Page