Solved

Reading a float(?)

Posted on 2001-06-15
15
1,093 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
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

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

[Live Webinar] The Cloud Skills Gap

As Cloud technologies come of age, business leaders grapple with the impact it has on their team's skills and the gap associated with the use of a cloud platform.

Join experts from 451 Research and Concerto Cloud Services on July 27th where we will examine fact and fiction.

Question has a verified solution.

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

Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
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…
There's a multitude of different network monitoring solutions out there, and you're probably wondering what makes NetCrunch so special. It's completely agentless, but does let you create an agent, if you desire. It offers powerful scalability …
Michael from AdRem Software explains how to view the most utilized and worst performing nodes in your network, by accessing the Top Charts view in NetCrunch network monitor (https://www.adremsoft.com/). Top Charts is a view in which you can set seve…
Suggested Courses
Course of the Month4 days, 21 hours left to enroll

635 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