strange read in of binary file

Z

zl2k

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();
 
Z

zl2k

zl2k said:
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

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
 
Z

zl2k

zl2k said:
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
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

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
 
J

James Kanze

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:

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.
 
J

James Kanze

On Apr 11, 4:40 pm, "Victor Bazarov" <[email protected]> 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.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,968
Messages
2,570,153
Members
46,699
Latest member
AnneRosen

Latest Threads

Top