0

UPDATED - I added 2 screen shots with 0.00 in the data and one with 1234.56 in the data

I am using an old VB6 set of code as 95% works to read a text file that gets converted and stored in MS SQL. The strings are all good however there are numbers mixed into the text binary file that I haven't figured out how to read. The original application the numbers are all currency however the hex dump of the numbers looks to be 4 byte numbers.

Either way I am not sure how to read the numbers into a local variable. Maybe I am not starting at the correct place in the data. In the example below I am starting at the <160>.

Here is a dump of the part of the binary file with 0.00 in the data:

enter image description here

Here is a dump of the part of the binary file with 1234.56 in the data:

enter image description here

Note the arrow point to where the data changed.

This is my last try but that doesnt work either.

Function ReadFloat(f As Integer, Optional ShowDB As Boolean = False) As String
    On Error GoTo 0

  Dim c As Single
  Dim S(4) As Byte
   Dim x As Integer
   Dim flt As Single


  Get f, , S

   For x = 1 To 4
    Debug.Print x & "  " & S(x) & "   " & Hex(S(x)); "='" & Chr(S(x)) & "'"

   Next x

   CopyMemory flt, S, 4
3
  • 1
    Without knowing the exact format of the file it's going to be difficult. Currency is stored as 8 bytes, so it could still be that in the binary file. Do you know the numbers you are expecting to see from the binary file? In other words, could you look for them in the binary file? It may also be useful to get hold of a hex editor so you can see the bytes tabulated. Commented Aug 22, 2017 at 15:50
  • I showed the blue image from the VEDIT editor. I am not sure how to see the bytes tabulated but that would be sweet. I will create a new record with one number and make sure everything else is 0. Hoping that will help decipher this. Commented Aug 22, 2017 at 16:19
  • @MarkWorsnop: are you sure that there is only room for 4 bytes? can you put a bigger amount inside your test file? Otherwise i would guess that this is a fixed format with just only 2 decimal digits. Commented Aug 22, 2017 at 23:54

2 Answers 2

1

My initial inspection suggests that the bytes starting:

40 E2 01

are what you're looking for. These are stored little endian, so 01E240 is hex for 123456 in decimal. So my guess would be 32 bit integers (4 byte long type). You can test this by using -0.01 as a value, this should give:

... FF FF FF FF ...

in the file.

If you're only interested in reading just these values then you can read and discard the first x values. Something like:

Dim yDiscard(123) As Byte
...
Get #1, ,yDiscard

Or alternatively, just seek to the position first before reading:

Seek #1, 123

To work out what byte values to expect in general, I found the following to be useful. Just run the code in a module:

Sub main()
    Dim lValue As Long
    Dim cValue As Currency
    Dim nValue As Single
    Dim dValue As Double
    Dim sValue As String
    Dim vValue As Variant

    lValue = 123456
    cValue = 1234.56
    nValue = 1234.56
    dValue = 1234.56
    sValue = "1234.56"
    vValue = CDec(1234.56)

    Open "c:\test1.bin" For Binary As 1
    Open "c:\test2.bin" For Binary As 2
    Open "c:\test3.bin" For Binary As 3
    Open "c:\test4.bin" For Binary As 4
    Open "c:\test5.bin" For Binary As 5
    Open "c:\test6.bin" For Binary As 6

    Put #1, , lValue
    Put #2, , cValue
    Put #3, , nValue
    Put #4, , dValue
    Put #5, , sValue
    Put #6, , vValue

    Close #1
    Close #2
    Close #3
    Close #4
    Close #5
    Close #6
End Sub

You can then inspect each file in a hex editor (I use MadEdit but anything will do).

It's probably useful to also try simple values like 1.00, 2.00, 10.00, -1.00 and see how the bytes differ each time.

This may also be informative (fairly in depth):

http://www.codeguru.com/vb/gen/vb_misc/algorithms/article.php/c7495/How-Visual-Basic-6-Stores-Data.htm

And to actually answer the question, something like the following will read a 32 bit integer and convert to currency:

Function ReadAmount(iFileHandle As Integer, lFileBytePosition As Long) As Currency
    Dim lValue As Long

    Seek #iFileHandle, lFileBytePosition
    Get #iFileHandle, , lValue

    ReadAmount = CCur(lValue) / 100
End Function

There's no need for an intermediate byte array.

Sign up to request clarification or add additional context in comments.

2 Comments

The ReadAmount works perfectly. I kept looking for 8 byte decimal numbers so was blind looking for the trees in the forest. Thank you so much for the detailed answer.
Hopefully not bigger than 2GB, or you'll hit the limit for a Long data type. In which case you'll have to resort to using the Windows API, for example using SetFilePointerEx, that would be fun...
0

True floating point are bad when using currency, so actually your number is an integer with fixed point. First : put them in an integer variable (type Long) Second : divide by 100 to get back the decimal !

Straightforward method to convert it to single:

Dim S(4) As Byte 'your 4 bytes, like (1)=&H40, (2)=&HE2 (3)=&H01, (4)=&H00

Dim Buffer As Long
Buffer = S(4) * 16777116 Or S(3) * 65536 Or S(2) * 256 Or S(1)
Dim flt As Single
flt = Buffer / 100

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.