ifstream

D

Dart

ifstream ifs;
ifs.open("whatever.bin", ios::in | ios::binary);

How to set flag above so that if "whatever.bin" file missing, rather than
create a new file named "whatever.bin", but providing a way to detect the
error?

ifs.read((char *)p, 4);

Does each "read()" call above read only in bytes? Is it possible to
directly read in ints? Like ifs.read((int *)p, 1);

ifs.read((char *)p, 16);

How to obtain 4 ints out of p pointing to 16 bytes?

Thanks!
 
V

Victor Bazarov

Dart said:
ifstream ifs;
ifs.open("whatever.bin", ios::in | ios::binary);

How to set flag above so that if "whatever.bin" file missing, rather than
create a new file named "whatever.bin", but providing a way to detect the
error?

Since you use 'ios::in', it shouldn't create. Why would it?

The Standard says that 'open' can set 'failbit', so after an attempt
to open a file, check if it has been in fact open:

if (ifs.is_open())
...
ifs.read((char *)p, 4);

Does each "read()" call above read only in bytes? Is it possible to
directly read in ints? Like ifs.read((int *)p, 1);

No, the low-level I/O works only in chars.
ifs.read((char *)p, 16);

How to obtain 4 ints out of p pointing to 16 bytes?

Often you can simply reinterpret_cast the pointer to treat your 'p'
as an array of ints. It's not portable, of course, use at your own
risk.

Victor
 
B

Buster

Dart said:
ifstream ifs;
ifs.open("whatever.bin", ios::in | ios::binary);

If portability (of the data files) is a concern you should consider
doing formatted input and output instead (with said:
How to set flag above so that if "whatever.bin" file missing, rather than
create a new file named "whatever.bin", but providing a way to detect the
error?

On my system the behaviour is already what you're asking for. I can't
attest to the portability of this, as the standard just says that the
file is opened "as if" by calling fopen, and my documentation for fopen
isn't clear on this point.
ifs.read((char *)p, 4);

Does each "read()" call above read only in bytes?
Yes.

Is it possible to directly read in ints? Like ifs.read((int *)p, 1);

It depends what you mean by directly. Here's an idea:

template <typename T>
std::istream & read_natively (std::istream & stream, T & var)
{
char * mem = reinterpret_cast <char *> (& var);
return stream.read (mem, sizeof var);
}

// ...

int x;
if (read_natively (ifs, x)) /* ... */;
ifs.read((char *)p, 16);

How to obtain 4 ints out of p pointing to 16 bytes?

int a [4];
read_natively (ifs, a); // might not work on broken old compilers
 
D

Dart

Victor Bazarov said:
ifs.read((char *)p, 16);

Often you can simply reinterpret_cast the pointer to treat your 'p'
as an array of ints. It's not portable, of course, use at your own
risk.

Victor
Is this going to work?

int arr[4];
arr = reinterpret_cast<int *>(p);

Thanks!
 
K

Kevin Goodsell

Dart said:
Is this going to work?

int arr[4];
arr = reinterpret_cast<int *>(p);

Of course not. You can't assign to an array.

int *ip = reinterpret_cast<int *>(p);

-Kevin
 
B

Buster

Dart said:
Is this going to work?

int arr[4];
arr = reinterpret_cast<int *>(p);

No, it's a syntax error. Your compiler would have told you this
if you had taken a minute to try. What was it you wanted to do?
 
S

Siemel Naran

If portability (of the data files) is a concern you should consider
doing formatted input and output instead (with << and >>).

Are you talking of the big endian and little endian thing?

13 = 0000 1101

may be stored as

0000 1101
1011 0000
 
J

John Harrison

Siemel Naran said:
Are you talking of the big endian and little endian thing?

13 = 0000 1101

may be stored as

0000 1101
1011 0000

Big endian, little endian is just one example of the way in which binary I/O
is completely non-portable between different systems.

john
 
K

Kevin Goodsell

John said:
Big endian, little endian is just one example of the way in which binary I/O
is completely non-portable between different systems.

Depends a lot on how you use it. There are hundreds of binary file
formats in common use that are portable to most common systems.

-Kevin
 
J

John Harrison

Kevin Goodsell said:
Depends a lot on how you use it. There are hundreds of binary file
formats in common use that are portable to most common systems.

That's the 'in the real world' answer, which is fair comment. I was giving
the 'C++ standard' answer which says that binary I/O is non portable.

john
 
K

Kevin Goodsell

John said:
That's the 'in the real world' answer, which is fair comment. I was giving
the 'C++ standard' answer which says that binary I/O is non portable.

Honestly, I'm not sure I understand why. The only really hard problem I
see is the possibility of CHAR_BIT > 8. Other problems I can think of
are hard, but not impossible (like floating point values -- you can
choose a standard format, but translating to and from it could be quite
tricky, and precision may be lost).

Would you care to explain your take on it?

-Kevin
 
J

John Harrison

Kevin Goodsell said:
Honestly, I'm not sure I understand why. The only really hard problem I
see is the possibility of CHAR_BIT > 8. Other problems I can think of
are hard, but not impossible (like floating point values -- you can
choose a standard format, but translating to and from it could be quite
tricky, and precision may be lost).

Would you care to explain your take on it?

On what? The decision of the C++ standards committee to say that binary I/O
is non-portable? I would imagine that they just didn't want to constrain
implementations of C++. For instance with floating point formats, you would
either have to force every one to use a particular format internally or to
use different formats internally and convert on input or output. The first
is obviously a non-starter with the different floating point hardware out
there, and the second rather defeats the purpose of binary I/O which is
maximum efficiency without regard for anything else. If you are going to do
conversions then you might as well convert to text.

At least that's my take on it.

john
 
K

Kevin Goodsell

John said:
On what? The decision of the C++ standards committee to say that binary I/O
is non-portable?

Could you indicate where they say that? I'd like to take a look at it.
I would imagine that they just didn't want to constrain
implementations of C++. For instance with floating point formats, you would
either have to force every one to use a particular format internally or to
use different formats internally and convert on input or output. The first
is obviously a non-starter with the different floating point hardware out
there, and the second rather defeats the purpose of binary I/O which is
maximum efficiency without regard for anything else. If you are going to do
conversions then you might as well convert to text.

At least that's my take on it.

Fair enough. Though it's certainly possible that one might want to read
and/or write files in one of the many already-in-use binary formats.

-Kevin
 
R

Rolf Magnus

Kevin said:
Honestly, I'm not sure I understand why. The only really hard problem
I see is the possibility of CHAR_BIT > 8. Other problems I can think
of are hard, but not impossible (like floating point values -- you can
choose a standard format, but translating to and from it could be
quite tricky, and precision may be lost).

Another problem is that on one system, int might be 16 bit, on another
32 bit, and on the third 24 bit. Then there could be alingment
problems, writing something to disk with another alignment than would
be needed when read in again.
 
K

Kevin Goodsell

Rolf said:
Another problem is that on one system, int might be 16 bit, on another
32 bit, and on the third 24 bit. Then there could be alingment
problems, writing something to disk with another alignment than would
be needed when read in again.

This shouldn't be a problem if it's done properly, though. The file
format dictates the size of the field and the byte order -- just read in
that many bytes into a byte array, then shift and add those bytes into
your variable as needed (just make sure you choose a type that's large
enough).

-Kevin
 
J

John Harrison

Kevin Goodsell said:
Could you indicate where they say that? I'd like to take a look at it.

I'm not sure that they do say it in so many words. I think you'd have to
cross reference several sections to work it out. If anyone else knows better
I'd also be interested.

john
 
D

Dart

Kevin Goodsell said:
Dart said:
Is this going to work?

int arr[4];
arr = reinterpret_cast<int *>(p);

Of course not. You can't assign to an array.

int *ip = reinterpret_cast<int *>(p);

-Kevin

The test program is:

char a[4];
a[0] = 0x12;
a[1] = 0x34;
a[2] = 0x56;
a[3] = 0x67;

int* intp = reinterpret_cast<int *>(a);
cout << hex << intp;

The output is: 0012FED4.

Why 0x12, 0x34, 0x56, 0x67 not displayed?

When declaring an array, whatever_array[N], is it always that all elements
in the array are consecutive in memory?
 
S

Siemel Naran

The test program is:

char a[4];
a[0] = 0x12;
a[1] = 0x34;
a[2] = 0x56;
a[3] = 0x67;

int* intp = reinterpret_cast<int *>(a);
cout << hex << intp;

Note this is disaster if sizeof(int) is more than 4 bytes. There are some 8
byte machines out there.
The output is: 0012FED4.

Why 0x12, 0x34, 0x56, 0x67 not displayed?

You're printing the address of the pointer. Probably you meant to use *intp
cout << hex << *intp;

I'm using Borland 6, AMD, Windows ME. My result is with *intp is
"67563412". Would this be big endian or little endian?
When declaring an array, whatever_array[N], is it always that all elements
in the array are consecutive in memory?

Yes.
 

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

No members online now.

Forum statistics

Threads
473,776
Messages
2,569,603
Members
45,196
Latest member
ScottChare

Latest Threads

Top