Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > reading binary file into memory. Converting from char to uint32,float, double, ASCII strings etc (static_cast< > ?)

Reply
Thread Tools

reading binary file into memory. Converting from char to uint32,float, double, ASCII strings etc (static_cast< > ?)

 
 
Ian Collins
Guest
Posts: n/a
 
      10-15-2011
On 10/16/11 11:39 AM, Martin Jørgensen wrote:
> On Oct 15, 11:35 pm, Richard Damon<(E-Mail Removed)>
> wrote:
>> On 10/15/11 3:00 PM, someone wrote:

> ==
>>> I'm stuck...

>>
>>> And what about big endian / little endian? I'm confused. Looking
>>> forward to hear from you!

>>
>> First, what is the first byte in the file? you are saying that you are
>> expecting it to be 72 but you are getting 49. Have you looked at the file..

>
> Good point. The first four bytes of the input file has the values:
> [048h 00h 00h 00h] (hexadecimal, I used a hex editor to see this). And
> 0x48H = 72 decimal... I don't even know if this is little endian or
> not, but what I find very strange is the number 49 then... That number
> makes no sense to me (why is it adding 1, if it's printing the number
> in hexadecimal? What's it thinking?)..?


If you are in a 32 bit little endian (x86) machine, this will work:

#include <iostream>

int main()
{
char tmp[4] = {0x48,0,0,0};

std::cout << *reinterpret_cast<int*>(tmp) << std::endl;

return 0;
}

If not, you will have to build the integer value from the individual
bytes. For example if the data were written on a big endian machine:

char be[4] = {0,0,0,0x48};

int n = be[3] + (be[2]<< + (be[1]<<16) + (be[0]<<24);

std::cout << n << std::endl;

--
Ian Collins
 
Reply With Quote
 
 
 
 
someone
Guest
Posts: n/a
 
      10-15-2011
On 16 Okt., 01:33, Ian Collins <(E-Mail Removed)> wrote:
> On 10/16/11 11:39 AM, Martin Jørgensen wrote:
> If you are in a 32 bit little endian (x86) machine, this will work:
>
> #include <iostream>
>
> int main()
> {
> * *char tmp[4] = {0x48,0,0,0};
>
> * *std::cout << *reinterpret_cast<int*>(tmp) << std::endl;
>
> * *return 0;
>
> }
>
> If not, you will have to build the integer value from the individual
> bytes. *For example if the data were written on a big endian machine:
>
> * *char be[4] = {0,0,0,0x48};
>
> * *int n = be[3] + (be[2]<< + (be[1]<<16) + (be[0]<<24);
>
> * *std::cout << n << std::endl;



THANKS A LOT TO ALL WHO HELPED!

I'll get back if I get problems with reading the rest of the file,
however I think (I hope) everything will work out now
 
Reply With Quote
 
 
 
 
Richard Damon
Guest
Posts: n/a
 
      10-15-2011
On 10/15/11 7:32 PM, someone wrote:
> On 16 Okt., 01:12, someone<(E-Mail Removed)> wrote:
>> integer value of 72, even though I cannot get it right yet... Guess
>> I'm casting incorrectly from char* to int.

>
> Oooops... Stupid me! I had outcommented the correct file name and used
> a much smaller working file in the line: infile.open("DELETEME.res",
> ios::in|ios::binary)
>
> --- sorry guys, maybe it's too late to work for me now!
>
>
> Last question for today and I shall soon close the thread: Can I ask
> you which of the following you think is the best to use (or suggest
> alternatives)?
>
>
> if (0) // my way of switching between alternate "solutions" when I
> want both in the code
> R1_begin = *(reinterpret_cast<unsigned char*> (&memblock[0]));//,
> 1, 'uint32',endianNess);
> else
> memcpy(&R1_begin,&memblock[0], sizeof(R1_begin));
>
>
> ?


The first doesn't do what you want. &memblock[0] is already a char* so
casting it to unsigned char* and dereferencing isn't going to make a big
change. If you did a cast to unsigned int*, that would be different.


You also shouldn't use reinterpret_cast here, static_cast is good
enough, and is actually what you want.

The memcpy is better, as the cast has the danger that some fields might
not line up on the right word boundaries in your data buffer. It also
says you can later change them to the network order calls later to make
your program more portable.
 
Reply With Quote
 
Pavel
Guest
Posts: n/a
 
      10-15-2011
someone wrote:
> Hi,
>
> Here's my program:
>
> ==========================
> #include<fstream>
> #include<iostream>
> #include<string>
> #include<sstream>
> #include<stdio.h>
> //#include<boost/cstdint.hpp> //<-- I know this is not the group to
> ask in, maybe unnecessary
>
> using namespace std;
>
>
> int main( int argc, const char* argv[] )
> {
> ifstream:os_type fsize;
> char * memblock;
> ifstream infile;
>
> cout<< "Program to read SENSOR file (for FLEX5). Build on: "<<
> __DATE__<< " / "<< __TIME__<< endl;
>
> infile.open("DELETEME.res", ios::in|ios::binary);
>
> if (infile.is_open())
> {
> infile.seekg (0, ios::end); // go to end of file
> fsize = infile.tellg();
> infile.seekg (0, ios::beg); // go to beginning
>
> cout<< "Size of file is: "<< fsize<< " bytes."<< endl;
> memblock = new char [fsize];
>
> infile.read (memblock, fsize);
> infile.close();
> //cout<< "the complete file content is in memory"<< endl;
> }
> else
> cout<< "Unable to open file"<< endl;
>
> cout<< endl; // delimiter before program outputs read data
>
> int R1_begin;
> R1_begin = static_cast<typeof R1_begin> (memblock[0]);//, 1,
> 'uint32',endianNess);
> cout<< "Value = "<< R1_begin<< endl;
>
> delete[] memblock;
> return 0;
> }
> ==========================
>
> Problem:
>
> R1_begin is the first value read from a binary file. But it's wrong!
> It should be 72 but the program prints 49 out to the screen. So I
> cannot continue before I get this right. The first few bytes I'm going
> to read is:
>
> R1begin = 1 byte times sizeof 'uint32' = 4 bytes
> I1_I6 = 6 bytes times sizeof 'uint32' = 6x4 = 24 bytes
> TEXT = 40 ASCII characters of type 'char' = 40 bytes
> R1end = 1 byte times sizeof 'uint32' = 4 bytes
>
> Total bytes read = 4+24+40+4 = 72 bytes. That's why I must read 72
> bytes from the very first byte in the binary file... And I cannot
> solve this!
>
> Please help (and please provide hints for reading the next few bytes
> and how I should convert from data in memory into different data
> types). Later I also need to convert some bytes from memblock[ ] into
> floats and doubles...
>
> I'm stuck...
>
> And what about big endian / little endian? I'm confused. Looking
> forward to hear from you!


I think previous responders answered most of your questions. I just noticed few
other things that may go wrong with your code sooner or later:

1. No check the return value of infile.read().
2. memblock was not initiazlied so delete[] can coredump (I would just use
std::vector or unique_ptr with array deleter if implemented and I cared about
performance).

-Pavel
 
Reply With Quote
 
Richard Damon
Guest
Posts: n/a
 
      10-16-2011
On 10/15/11 6:43 PM, Martin Jørgensen wrote:
> On Oct 15, 11:45 pm, Ian Collins<(E-Mail Removed)> wrote:
>> On 10/16/11 10:17 AM, someone wrote:

>
>>>> The most convenient way to convert the byte order is to use the network
>>>> ordering functions (if your platform has them). See ntohl.

>>
>>> Sorry, I have absolutely no idea about any network functions...
>>> I was (pretty) sure that somebody had some code they could show here?
>>> This "ntohl" looks a bit confusing to me - besides that, it's not
>>> standard C++.

>>
>> They are typically macros, just look them up if you want to see how they
>> work.

>
> Ok.
>
>>>>> And what about big endian / little endian? I'm confused. Looking
>>>>> forward to hear from you!

>>
>>>> Google "endian"

>>
>>> I did it. But what I meant is, what are your thoughts about it, when
>>> reading a binary file like shown in my code?

>>
>> I use the network byte order functions, that's what they are there for.

>
> Hmm... Based on my output to Richard - do I then have an endian
> problem? Sorry I'm a bit too unexperienced to fully understand this
> yet. A few replies and I think I'll understand it..
>
> Thanks a lot for your (you, Richard and Ebenezer) help so far!


Your data in the file is little endian. You have a problem if your
processor is not little endian.
 
Reply With Quote
 
someone
Guest
Posts: n/a
 
      10-16-2011
On 16 Okt., 03:37, Richard Damon <(E-Mail Removed)> wrote:
> On 10/15/11 6:43 PM, Martin Jørgensen wrote:
> > Hmm... Based on my output to Richard - do I then have an endian
> > problem? Sorry I'm a bit too unexperienced to fully understand this
> > yet. A few replies and I think I'll understand it..

>
> > Thanks a lot for your (you, Richard and Ebenezer) help so far!

>
> Your data in the file is little endian. You have a problem if your
> processor is not little endian.


Yep... Currently I think there's no problem (based on the first
unsigned integer, which is 4 bytes so now I don't want to learn more
than I can absorb)
 
Reply With Quote
 
someone
Guest
Posts: n/a
 
      10-16-2011
On 16 Okt., 01:56, Pavel
<(E-Mail Removed)> wrote:
> someone wrote:
> I think previous responders answered most of your questions. I just noticed few
> other things that may go wrong with your code sooner or later:
>
> 1. No check the return value of infile.read().


Ah, thanks a lot. I changed it into this:

if (infile.is_open())
{
infile.seekg (0, ios::end); // go to end of file
fsize = infile.tellg();
infile.seekg (0, ios::beg); // go to beginning

cout << "Size of file is: " << fsize << " bytes." << endl;
memblock = new char[fsize];

infile.read (memblock, fsize);
if (!infile)
{
cout << "Some error occured while reading the file, after: " <<
infile.gcount() << " bytes..." << endl;
return(1);
}
infile.close();
//cout << "the complete file content is in memory" << endl;
}
else
cout << "Unable to open file" << endl;


> 2. memblock was not initiazlied so delete[] can coredump (I would just use
> std::vector or unique_ptr with array deleter if implemented and I cared about
> performance).


Huh? I don't understand this. Even though it was not initialized, it
has been allocated and therefore I try to clean up in the end. With
the command:

infile.read (memblock, fsize);

I guess that I'm initializing it... Or what do you suggest?
I can't see why it should coredump, so please advice and thanks


 
Reply With Quote
 
Ian Collins
Guest
Posts: n/a
 
      10-16-2011
On 10/16/11 07:23 PM, someone wrote:
> On 16 Okt., 03:37, Richard Damon<(E-Mail Removed)> wrote:
>> On 10/15/11 6:43 PM, Martin Jørgensen wrote:
>>> Hmm... Based on my output to Richard - do I then have an endian
>>> problem? Sorry I'm a bit too unexperienced to fully understand this
>>> yet. A few replies and I think I'll understand it..

>>
>>> Thanks a lot for your (you, Richard and Ebenezer) help so far!

>>
>> Your data in the file is little endian. You have a problem if your
>> processor is not little endian.

>
> Yep... Currently I think there's no problem (based on the first
> unsigned integer, which is 4 bytes so now I don't want to learn more
> than I can absorb)


If you are happy that the file's number representations match your
machine's and portability isn't an issue, why don't you just stream the
values in directly rather than buggering about with a buffer?

int R1_begin;

infile >> R1_begin;

--
Ian Collins
 
Reply With Quote
 
Ian Collins
Guest
Posts: n/a
 
      10-16-2011
On 10/16/11 09:04 PM, Paavo Helde wrote:
> Ian Collins<(E-Mail Removed)> wrote in news:9fvgseFpouU1
> @mid.individual.net:
>>
>> If you are happy that the file's number representations match your
>> machine's and portability isn't an issue, why don't you just stream the
>> values in directly rather than buggering about with a buffer?
>>
>> int R1_begin;
>>
>> infile>> R1_begin;

>
> Maybe because that the file is binary, but the stream>> operator assumes
> it is formatted ASCII text?


Oops...

--
Ian Collins
 
Reply With Quote
 
Stefan Ram
Guest
Posts: n/a
 
      10-16-2011
someone <(E-Mail Removed)> writes:
>infile.open("DELETEME.res", ios::in|ios::binary);
>(...) infile.seekg (0, ios::end); // go to end of file


»seekg« seems to be defined in ISO/IEC 14882:2011
(in 27.7.2.3p40) using »pubseekoff« , which is defined
(in 27.6.3.2.2p2) in terms of »seekoff« , which is defined
(in 27.6.3.4.2p3) based on »::std::fseek« for file-base streams
(in 27.9.1.5p13); and ISO/IEC 9899:1990 explains about »fseek«:

»A binary stream need not meaningfully support
fseek calls with a whence value of SEEK_END.«

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
converting char to float (reading binary data from file) itdevries C++ 17 05-31-2008 08:33 AM
converting char to int (reading from a binary file) itdevries C++ 12 05-18-2008 09:42 AM
(const char *cp) and (char *p) are consistent type, (const char **cpp) and (char **pp) are not consistent lovecreatesbeauty C Programming 1 05-09-2006 08:01 AM
/usr/bin/ld: ../../dist/lib/libjsdombase_s.a(BlockGrouper.o)(.text+0x98): unresolvable relocation against symbol `std::basic_ostream<char, std::char_traits<char> >& std::endl<char, std::char_traits<char> >(std::basic_ostre silverburgh.meryl@gmail.com C++ 3 03-09-2006 12:14 AM
Question about reading a big binary file and write it into several text (ascii) files Albert Tu Python 2 01-25-2005 03:56 AM



Advertisments