| | |
A few questions about binary i/o..
Please support our C++ advertiser: Programming Forums - DaniWeb Sister Site
![]() |
I have a few ( slightly related ) questions about binary i/o in C++, I can't seem to find full answers to these anywhere..
- Is there any way to tell if an i/ostream passed to a function has been opened in binary or text mode?
- If not, are there any nuances to look out for when using put/read/write methods on an i/ostream that was opened in text mode? Would a process that assumes an i/ostream was binary, and worked 'correctly' in that case, be in any way incorrect if the stream it used was instead opened in text mode?
- How does endian-ness work? If two bytes A and B are written ( in that order ) into a file using put, then read on a machine with reversed endian-ness, do the bytes come out in a different order ( i.e. B, A ), or do they come out in the order A, B, but with the actual bits themselves being backwards? Or does the ( binary mode ) i/ostream normalize this so that it's not a problem? What if the bytes are written using ostream.write directly from an array reinterpret_casted to a char * ? ( and then read using istream.read )
- Is there any way to tell if an i/ostream passed to a function has been opened in binary or text mode?
- If not, are there any nuances to look out for when using put/read/write methods on an i/ostream that was opened in text mode? Would a process that assumes an i/ostream was binary, and worked 'correctly' in that case, be in any way incorrect if the stream it used was instead opened in text mode?
- How does endian-ness work? If two bytes A and B are written ( in that order ) into a file using put, then read on a machine with reversed endian-ness, do the bytes come out in a different order ( i.e. B, A ), or do they come out in the order A, B, but with the actual bits themselves being backwards? Or does the ( binary mode ) i/ostream normalize this so that it's not a problem? What if the bytes are written using ostream.write directly from an array reinterpret_casted to a char * ? ( and then read using istream.read )
Plato forgot the nullahedron..
•
•
•
•
Originally Posted by MattEvans
- Is there any way to tell if an i/ostream passed to a function has been opened in binary or text mode?
C++ Syntax (Toggle Plain Text)
#include <fstream> #include <iostream> namespace EdRules { using namespace std; int OPEN_MODE = 0; void foo(ostream& os) { switch (os.iword(OPEN_MODE)) { case 0: cout << "Binary\n"; break; case 1: cout << "Text\n"; break; } } } int main() { using namespace std; using namespace EdRules; OPEN_MODE = cout.xalloc(); cout.iword(OPEN_MODE) = 0; foo(cout); cout.iword(OPEN_MODE) = 1; foo(cout); }
•
•
•
•
Originally Posted by MattEvans
- If not, are there any nuances to look out for when using put/read/write methods on an i/ostream that was opened in text mode? Would a process that assumes an i/ostream was binary, and worked 'correctly' in that case, be in any way incorrect if the stream it used was instead opened in text mode?
•
•
•
•
Originally Posted by MattEvans
- How does endian-ness work? If two bytes A and B are written ( in that order ) into a file using put, then read on a machine with reversed endian-ness, do the bytes come out in a different order ( i.e. B, A ), or do they come out in the order A, B, but with the actual bits themselves being backwards?
•
•
•
•
Originally Posted by MattEvans
Or does the ( binary mode ) i/ostream normalize this so that it's not a problem? What if the bytes are written using ostream.write directly from an array reinterpret_casted to a char * ? ( and then read using istream.read )
If at first you don't succeed, keep on sucking until you do succeed.
Thanks for the info on storing things into the i/ostream directly, that could come in useful elsewhere
, but, the reason I wanted to determine the open mode is to stop a method being inadvertently called with a stream in the wrong mode.. so, that won't work.. but I seem to get the same results in light testing when writing to a stream opened in 'the wrong mode' anyway.. hence my second question.
The endian-ness thing, I'm still not sure I get it... a more specific example of what I'm doing, writing 32-bit floats to and from binary files, I don't have access to a machine with a different endian-ness.. But, lets say I work on a PC, and I want my files to open in a Mac ( which is apparently reverse endianess to PC ).. [ I am happy to assume that floats are 32-bit on my targets.. and that they're represented the same... although, is that even a safe assumption on Windows, Mac, Linux? See I really don't want to have to resort to a dodgy handrolled file representation for non-integers, and using a text representation for floating point arrays never really appealled to me. ]
Anyway, assuming that the representation is the same.. if I do this:
Will it work ( i.e. will the read value be equal the written value ) if the second half of that process is done on a reverse-endian machine? Or is it better ( or no change atall ) to do this?
Or, is it necessary to reverse the order of the bits in each byte read if it is determined that the machine reading the file is 'backwards' ?
, but, the reason I wanted to determine the open mode is to stop a method being inadvertently called with a stream in the wrong mode.. so, that won't work.. but I seem to get the same results in light testing when writing to a stream opened in 'the wrong mode' anyway.. hence my second question.The endian-ness thing, I'm still not sure I get it... a more specific example of what I'm doing, writing 32-bit floats to and from binary files, I don't have access to a machine with a different endian-ness.. But, lets say I work on a PC, and I want my files to open in a Mac ( which is apparently reverse endianess to PC ).. [ I am happy to assume that floats are 32-bit on my targets.. and that they're represented the same... although, is that even a safe assumption on Windows, Mac, Linux? See I really don't want to have to resort to a dodgy handrolled file representation for non-integers, and using a text representation for floating point arrays never really appealled to me. ]
Anyway, assuming that the representation is the same.. if I do this:
c++ Syntax (Toggle Plain Text)
int main( void ) { std::ofstream out( "test.bin", std::ios::binary | std::ios::out | std::ios::trunc ); const float f1 = 123.456f; out.write( reinterpret_cast< const char * >( &f1 ), sizeof( float ) ); out.close( ); std::ifstream in( "test.bin", std::ios::binary | std::ios::in ); float f2 = 0.0f; in.read( reinterpret_cast< char * >( &f2 ), sizeof( float ) ); in.close( ); assert( f1 == f2 ); }
c++ Syntax (Toggle Plain Text)
int main( void ) { std::ofstream out( "test.bin", std::ios::binary | std::ios::out | std::ios::trunc ); const float f1 = 123.456f; const char * c1 = reinterpret_cast< const char * >( &f1 ); for( size_t i = 0; i < sizeof( float ); ++i ) { out.put( c1[ i ] ); } out.close( ); std::ifstream in( "test.bin", std::ios::binary | std::ios::in ); float f2 = 0.0f; char * c2 = reinterpret_cast< char * >( &f2 ); for( size_t i = 0; i < sizeof( float ); ++i ) { c2[ i ] = in.get( ); } in.close( ); assert( f1 == f2 ); }
Plato forgot the nullahedron..
Edward's rule of thumb for binary I/O is that if you use read() and write(), the file is not portable. If you want portable binary I/O you need to deconstruct the object and write the bytes manually, then read them back in the same order they were written and reconstruct the object manually. That way the result is the same regardless of what system you process the file on.
The manual approach is almost always too involved to be worth it, so for portability, a standardized text format is the way to go.
The manual approach is almost always too involved to be worth it, so for portability, a standardized text format is the way to go.
If at first you don't succeed, keep on sucking until you do succeed.
I'm aware of potential issues involved when directly writing struct values to binary, so I already break the objects into primitives, but the smallest primitive I can break down to is a float, I'm happy to do this, it makes a certain amount of sense in a context which is basically, a load of arrays of float and uint32_t, with only a very tiny amount of considered structure ( a 16 byte header for each group of arrays, which may be hundreds/thousands of elements long ). The data is certainly not easily human-readable/writeable, so I wouldn't gain that usual advantage of a text format, only the portability. In any other situation though, I'd certainly go for a text format.
All I really need is a ( somewhat ) platform independant way of storing individual floats in binary format, I say somewhat platform independant, since PC and Mac are the only targets I'm focusing on.
But, based on what you've said, I guess that the second piece of code I posted would work ( reading and writing each byte of each float one at a time using get/put, and always reconstructing in the same order ), as long as floats are 32-bit, and are represented in the same way at bit-level on the target platforms...
All I really need is a ( somewhat ) platform independant way of storing individual floats in binary format, I say somewhat platform independant, since PC and Mac are the only targets I'm focusing on.
But, based on what you've said, I guess that the second piece of code I posted would work ( reading and writing each byte of each float one at a time using get/put, and always reconstructing in the same order ), as long as floats are 32-bit, and are represented in the same way at bit-level on the target platforms...
Plato forgot the nullahedron..
•
•
•
•
Originally Posted by MattEvans
But, based on what you've said, I guess that the second piece of code I posted would work
C++ Syntax (Toggle Plain Text)
#include <iostream> float ToFloat(const unsigned char *bytes) { unsigned long temp = 0; temp |= (bytes[0] & 0xFF) << 24; temp |= (bytes[1] & 0xFF) << 16; temp |= (bytes[2] & 0xFF) << 8; temp |= (bytes[3] & 0xFF) << 0; return *reinterpret_cast<float*>(&temp); } unsigned char *FromFloat(float value, unsigned char *bytes) { unsigned long *temp = reinterpret_cast<unsigned long*>(&value); bytes[0] = static_cast<unsigned char>((*temp >> 24) & 0xFF); bytes[1] = static_cast<unsigned char>((*temp >> 16) & 0xFF); bytes[2] = static_cast<unsigned char>((*temp >> 8) & 0xFF); bytes[3] = static_cast<unsigned char>((*temp >> 0) & 0xFF); return bytes; } int main() { using namespace std; float value = 247.548f; unsigned char bytes[4]; cout << fixed << ToFloat(FromFloat(value, bytes)) << '\n'; }
If at first you don't succeed, keep on sucking until you do succeed.
•
•
•
•
It's all about the interpretation of the bytes when loaded into memory that matters, not how they're stored. If the first machine writes A,B and the second machine reads A,B, the values will be interpreted differently because to the first machine A,B means A,B, but to the second machine A,B means B,A.••••- How does endian-ness work? If two bytes A and B are written ( in that order ) into a file using put, then read on a machine with reversed endian-ness, do the bytes come out in a different order ( i.e. B, A ), or do they come out in the order A, B, but with the actual bits themselves being backwards?
Matt, see this
Last edited by WaltP; Aug 18th, 2008 at 2:31 pm.
The 3 Laws of the Procrastination Society:
1) Never do today that which can be put off until tomorrow
2) Tomorrow never comes
1) Never do today that which can be put off until tomorrow
2) Tomorrow never comes
No really. You said "It's all about the interpretation of the bytes when loaded into memory that matters, not how they're stored." I'm saying you must know how they are stored or you can't properly read the data.
I think I know what you were trying to say, but it wasn't clear.
I think I know what you were trying to say, but it wasn't clear.
The 3 Laws of the Procrastination Society:
1) Never do today that which can be put off until tomorrow
2) Tomorrow never comes
1) Never do today that which can be put off until tomorrow
2) Tomorrow never comes
![]() |
Similar Threads
- I have a few questions to be patched up can anybody get these to me ? (C++)
- searching and inserting node in a binary search tree (C)
- Using binary operators! (C)
- Binary Numbers (Computer Science)
- dont know where to start (C)
- Real number to binary? (C)
- How do I Take in Hexidecimal input out put binary, decimal, and octal (Java)
- coding a complete binary tree with Dev-C++ (C++)
Other Threads in the C++ Forum
- Previous Thread: Matrix - Matrix multiplication
- Next Thread: cant compile my program
Views: 1304 | Replies: 10
| Thread Tools | Search this Thread |
Tag cloud for C++
6 api application array arrays assignment beginner binary bitmap c++ c/c++ calculator char class classes code coding compile compiler console conversion convert count data database delete developer display dll email encryption error file forms fstream function functions game generator getline givemetehcodez graph homeworkhelper iamthwee ifstream image input int java lazy lib loop looping loops map math matrix memory multidimensional multiple newbie news node number output parameter pointer problem program programming project proxy python random read recursion recursive reference return sort sorting string strings struct template templates text tree url variable vector video visual visualstudio win32 windows winsock word wordfrequency wxwidgets






