Solved

Reading a float(?)

Posted on 2001-06-15
15
1,060 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
  • 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
 
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
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
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 50 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

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

In this tutorial I will show you how to use the Windows Speech API in Delphi. I will only cover basic functions such as text to speech and controlling the speed of the speech. SAPI Installation First you need to install the SAPI type library, th…
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…
Sending a Secure fax is easy with eFax Corporate (http://www.enterprise.efax.com). First, Just open a new email message.  In the To field, type your recipient's fax number @efaxsend.com. You can even send a secure international fax — just include t…
Polish reports in Access so they look terrific. Take yourself to another level. Equations, Back Color, Alternate Back Color. Write easy VBA Code. Tighten space to use less pages. Launch report from a menu, considering criteria only when it is filled…

747 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

Need Help in Real-Time?

Connect with top rated Experts

13 Experts available now in Live!

Get 1:1 Help Now