Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

Reading a float(?)

Posted on 2001-06-15
15
Medium Priority
?
1,099 Views
Last Modified: 2009-07-29
I have a piece of C (eurgh) code that I'm converting to Delphi (hooray). As part of it I need to read a file structure in and as it's a byte file I'm using FILE of BYTE. However (and it's here that my brain gave up) part of the structure contains a float value. Any idea how I read in a float value from a stream of bytes?

e.g.

VAR
  bFile  : FILE OF BYTE;
  rValue : DOUBLE;
...
  READ(bFile, byte1);
  READ(bFile, byte2);
  READ(bFile, rValue); ?!?!?!?!

I know that the reading of rValue is wrong but anybody got any ideas how it needs to be?

The Neil =:)
0
Comment
Question by:TheNeil
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 6
  • 4
  • 4
  • +1
15 Comments
 
LVL 8

Expert Comment

by:Cesario
ID: 6194311
Hi,


VAR
 bFile  : FILE;
 rValue : DOUBLE;
...
 Reset ( bFile, 1 );
 BlockRead(bFile, byte1,SizeOf(Byte));
 BlockREAD(bFile, byte2,SizeOf(Byte));
 BlockREAD(bFile, rValue, SizeOf(rValue);


good luck



Cesario
0
 
LVL 5

Author Comment

by:TheNeil
ID: 6194373
Thanks Cesario, that works perfectly, but (and here it comes) the file is stored in little-endian (Intel byte ordering) format so all the byte values are stores backwards. Using block read gets the values in in the wrong order and therefore gets the wrong value back out. Any ideas?

The Neil =:(
0
 
LVL 5

Author Comment

by:TheNeil
ID: 6194378
Thanks Cesario, that works perfectly, but (and here it comes) the file is stored in little-endian (Intel byte ordering) format so all the byte values are stores backwards. Using block read gets the values in in the wrong order and therefore gets the wrong value back out. Any ideas?

The Neil =:(
0
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
LVL 8

Expert Comment

by:Cesario
ID: 6194411
Yeah, read it in as an integer or cardinal, and then swap things around,
either with masks and shifts or by using asm instructions to do the
swap.
0
 
LVL 8

Expert Comment

by:Cesario
ID: 6194427
Hi

http://www.caos.dk/development/delphi/turnint.htm
http://www.rdrop.com/~cary/html/endian_faq.html

try to use the BSWAP and XCHG assembler instructions, respectively



function SWAP16(ASmallInt: SmallInt): SmallInt; register;
asm
  xchg al, ah
end;


function SWAP32 (AnInteger: Integer): Integer; register;
asm
  bswap eax;
end;

Best Regards

Cesario
0
 
LVL 5

Author Comment

by:TheNeil
ID: 6194465
Err, it's the float that's causing me problems (and I'm probably being dense) but doesn't all of this apply to int values only? If you can post me a piece of code that does it, the points are yours

The Neil =:(
0
 
LVL 8

Expert Comment

by:Cesario
ID: 6194534
Helle,

sorry, but I must leave the office now.. ( Client is waiting ).
So I try to post some code tommorow..


best Regards

Cesario
0
 
LVL 3

Expert Comment

by:f15iaf
ID: 6198001
try to use low level format functions
like
Fileopen
fileread
filewrite
fileclose

You can define with fileread how much bytes to read and
to any type whether it's byte or double;
0
 
LVL 5

Author Comment

by:TheNeil
ID: 6198045
f15iaf

Thanks for the suggestion but the problem isn't getting the data in from the file, it's getting it in the correct order and reassembling it. The data is stored as a float consisting of 4 bytes (no problems so far, blockread will handle that) BUT the bytes are stored in reverse order. If you read the four bytes straight into a float then you're not allowing for the reverse byte order. What I think needs to happen is that the four bytes need to be read in, re-ordered and THEN converted to a float (which has just given me an idea...)

The Neil =:)
0
 
LVL 3

Accepted Solution

by:
f15iaf earned 200 total points
ID: 6198065
first of all using double it's 8 byte real type you should use 4 byte real which is single;

Here is the code which reverses the bytes:
var
  hl:pchar;
  fl:single;
  h:char;
begin
        hl:=@fl;
        {read 4 bytes here to hl here by BlockREAD(bFile, hl,4)}
        h:=hl[0];
        hl[3]:=hl[0]
        hl[3]:=h;
        h:=hl[1];
        hl[2]:=hl[1]
        hl[2]:=h;
        {the fl here is the right 4 byte real}

end;
0
 
LVL 3

Expert Comment

by:f15iaf
ID: 6198142
Sorry this si the correct one


first of all using double it's 8 byte real type you should use 4 byte real which is single;

Here is the code which reverses the bytes:
var
 hl:pchar;
 fl:single;
 h:char;
begin
       hl:=@fl;
       {read 4 bytes here to hl here by BlockREAD(bFile, hl,4)}
       h:=hl[0];
       hl[0]:=hl[3]
       hl[3]:=h;
       h:=hl[1];
       hl[1]:=hl[2]
       hl[2]:=h;
       {the fl here is the right 4 byte real}

end;
0
 
LVL 5

Author Comment

by:TheNeil
ID: 6198539
Have you tried running this code? I've pasted it in (and uncommented the BlockRead and added the missing semi-colons) and it falls flat on it's face when it hits the line:

h:=hl[0];

It's causing an access violation

The Neil =:(
0
 
LVL 3

Expert Comment

by:f15iaf
ID: 6198570
I've found the bug use
blockread(bfile,fl,4);
and then
      hl:=@fl;
      h:=hl[0];
      hl[0]:=hl[3]
      hl[3]:=h;
      h:=hl[1];
      hl[1]:=hl[2]
      hl[2]:=h;
      {the fl here is the right 4 byte real}

end;


var
hl:pchar;
fl:single;
h:char;
begin
      blockread(bfile,fl,4);
      hl:=@fl;
      h:=hl[0];
      hl[0]:=hl[3]
      hl[3]:=h;
      h:=hl[1];
      hl[1]:=hl[2]
      hl[2]:=h;
      {the fl here is the right 4 byte real}

end;
0
 
LVL 5

Author Comment

by:TheNeil
ID: 6199487
Well this is a weird one. I should explain, I'm reading data from Quake 2 model files and the floats correspond to three scaling values that are used (and are stored in little endian order). When I use your code it's pulling out weird values (I'm not saying the code is wrong but ID's data files to be wrong...).

The byte sequences are as follows:

223 22 216 61  -> -1.0869504771e+19  ?
119 212 147 61 -> 8.6230725089e+33  ?

Yet if I put 0 0 0 0 in I get 0 out (which seems correct). As far as I can tell, the code is correct and it's re-ordering the bytes correctly and getting them effectively cast as a Single so I can't argue with it. Looks like you answered the question (but my overall problem hasn't been solved), so I'm giving you the points. This has me baffled though

The Neil =:)
0
 

Expert Comment

by:paolinoilpescatore
ID: 7093126
Hi "TheNeil", try this code. The trick is to have a true double var "pippo" at the same memory location of single 8 byte "TempByte". In this way you don't do anything !! "pippo" is ready to show the correct result in Edit1.Text. (in my code I suppose to have a file with data "filinp", then I open the file as you want "file of byte" and every time you want read a double var apply the short "for" loop and "pippo" is filled with the answer.

procedure TForm1.Button2Click(Sender: TObject);
var
  FilInp : file of byte;
  tempByte : array [0..7] of byte;
  pippo : double absolute TempByte;
  n : integer;
begin
  if od1.execute then begin
    AssignFile(FilInp, od1.FileName);
    Reset(FilInp);
    for n:=0 to 7 do begin
      Read(FilInp, TempByte[n]);
    end;
    CloseFile(FilInp);
    Edit1.Text:=FloatToStr(Pippo);
  end;
end;
0

Featured Post

On Demand Webinar: Networking for the Cloud Era

Did you know SD-WANs can improve network connectivity? Check out this webinar to learn how an SD-WAN simplified, one-click tool can help you migrate and manage data in the cloud.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Creating an auto free TStringList The TStringList is a basic and frequently used object in Delphi. On many occasions, you may want to create a temporary list, process some items in the list and be done with the list. In such cases, you have to…
Introduction I have seen many questions in this Delphi topic area where queries in threads are needed or suggested. I know bumped into a similar need. This article will address some of the concepts when dealing with a multithreaded delphi database…
Have you created a query with information for a calendar? ... and then, abra-cadabra, the calendar is done?! I am going to show you how to make that happen. Visualize your data!  ... really see it To use the code to create a calendar from a q…
In this video, Percona Solutions Engineer Barrett Chambers discusses some of the basic syntax differences between MySQL and MongoDB. To learn more check out our webinar on MongoDB administration for MySQL DBA: https://www.percona.com/resources/we…
Suggested Courses

704 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question