Reading Raw Data From Binary File

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
mrr19121970
Posts: 3
Joined: 22 Apr 2018, 02:37

Reading Raw Data From Binary File

22 Apr 2018, 02:45

Code: Select all

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn  ; Enable warnings to assist with detecting common errors.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.


	FileRead,BINFileData,%A_ScriptDir%\my.bin
	Pointer := &BINFileData

;https://autohotkey.com/board/topic/6946-binary-file-reading-and-writing/
	hFile := DllCall("CreateFile","Str",A_LoopFileName,"UInt",0x80000000,"UInt",3,"UInt",0,"UInt",3,"UInt",0,"UInt",0)

	if not hFile
	{
		MsgBox,16,%ApplicationTitle%,Can't open %A_LoopFileName%.
      	ExitApp
	}

    P1 := *(pointer)
    pointer++
    pointer++
    P2 := *(pointer)
    pointer++
    pointer++
    P3 := *(pointer)

    msgbox % P1 . A_Space . P2 . A_Space . P3

	DllCall("CloseHandle",UInt,hFile)

    exitapp
I have been struggling for many weeks getting my code to work, and now I have decided to help the experts.

my.bin contains 3 hex values

Code: Select all

98 C3 78
and I expect my message box to return "152 195 220", but it doesn't (returns 220 195 120). In the 1st byte any value below $7f seems to return correctly, however $80 and above return the wrong value.

Can anyone assist ?
just me
Posts: 9453
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Reading Raw Data From Binary File

23 Apr 2018, 04:47

You need to use the *c option to read binary data with FileRead. Otherwise, AHK will convert the file contents to the native encoding used by the script (ANSI/Unicode).
FileRead, BINFileData, *c %A_ScriptDir%\my.bin
Also, the link within your code is outdated. You should consider to use the File Object instead.
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: Reading Raw Data From Binary File

23 Apr 2018, 05:20

- Here's an example:

Code: Select all

q:: ;read/write binary files
;create file
vPath := A_Desktop "\z bin " A_Now ".bin"
if !(oFile := FileOpen(vPath, "w")) ;empties file
	return
vList := "98 C3 78"
Loop, Parse, vList, % " "
	oFile.WriteUChar("0x" A_LoopField) ;appends data, advances pointer
oFile.Close()

;read file
vOutput := "", vOutputHex := ""
oFile := FileOpen(vPath, "r")
oFile.Pos := 0 ;necessary if file is UTF-8/UTF-16 LE
;note if the file is smaller than 3 bytes, ReadUChar will return zeros
Loop, 3
{
	vNum := oFile.ReadUChar() ;reads data, advances pointer
	vOutput .= (A_Index=1?"":" ") vNum
	vOutputHex .= (A_Index=1?"":" ") Format("{:02X}", vNum)
}
oFile.Close()
MsgBox, % vList "`r`n" vOutput "`r`n" vOutputHex
return

;==================================================

;read file alternative
vOutput := "", vOutputHex := ""
FileRead, vData, % "*c " vPath
Loop, 3
{
	vNum := NumGet(&vData, A_Index-1, "UChar")
	;vNum := *(&vData+A_Index-1)
	vOutput .= (A_Index=1?"":" ") vNum
	vOutputHex .= (A_Index=1?"":" ") Format("{:02X}", vNum)
}
oFile.Close()
MsgBox, % vList "`r`n" vOutput "`r`n" vOutputHex
return
- By "152 195 220", did you mean "152 195 120"? I.e. that just the first byte was wrong.
- Btw * to dereference a single byte is not available in AutoHotkey v2, so I would use NumGet with UChar.
- You use pointer++ twice, is this intended? You would retrieve bytes 1, 3, 5 of the file. Note: you can use pointer += 2.
- Why are you using DllCall with CreateFile?
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
mrr19121970
Posts: 3
Joined: 22 Apr 2018, 02:37

Re: Reading Raw Data From Binary File

23 Apr 2018, 06:09

just me wrote:Also, the link within your code is outdated. You should consider to use the File Object instead.
Yes, I am aware that the link is outdated, the code I wrote is very old. Infact I only just noticed that only the 1st byte is wrong recently.
jeeswg wrote:- By "152 195 220", did you mean "152 195 120"? I.e. that just the first byte was wrong.
Yes, only the 1st byte is wrong. Everything else is correct
jeeswg wrote: - You use pointer++ twice, is this intended? You would retrieve bytes 1, 3, 5 of the file. Note: you can use pointer += 2.
This is the intended behavior. The code is reading files from an 8 bit system.
jeeswg wrote:- Why are you using DllCall with CreateFile?
just me wrote:Also, the link within your code is outdated. You should consider to use the File Object instead.
I think the code is 10 years old infact. I will look into the new features added to AHK in the meantime.
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: Reading Raw Data From Binary File

23 Apr 2018, 06:47

- I meant to add after 'Why are you using DllCall with CreateFile?': AFAICS it doesn't actually do anything.
- I'm not sure what the significance of '8-bit system' is. Are you using an old Windows OS? I would have thought that if you wanted to read the first 3 bytes of a file, you would just read the first 3 bytes, on any PC. Perhaps you want to read the file in 2-byte blocks, and thus should use UShort instead of UChar.
- I didn't look too closely at your use of CreateFile, but I thought that potentially it might be overwriting the file. Why is it in the script?
- Sometimes with AutoHotkey if you have a pointer to a variable, but the variable is then discarded, the contents remain intact apart from the very first byte. E.g. if a variable is returned or is passed ByRef to a function, it should survive, otherwise a variable would be discarded by the function.
- [EDIT:] Btw if your file simply contained 98 C3 78, then retrieving bytes 1, 3, 5 would give 98 78 00 (or 98 78 ##, where ## would be whatever happened to be at that address space in AutoHotkey, if you used the FileRead and NumGet method).
- [EDIT:] If you gave some more info about what you're trying to do, it might be helpful, e.g. typically file types start with a particular sequence of bytes.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
mrr19121970
Posts: 3
Joined: 22 Apr 2018, 02:37

Re: Reading Raw Data From Binary File

23 Apr 2018, 12:43

This has resolved my issue:

Code: Select all


    File := FileOpen(A_LoopFileFullPath, "r") 
    if !IsObject(file)
    {
        MsgBox Can't open "%A_LoopFileFullPath%" for reading.
        return
    }

    Pointer := File.ReadUInt()
    File.Close()

    P1 := JustHex(Pointer,8)
    FileDest := "0x" . Substr(P1,5,4)
    FileDestX := Substr(P1,5,4)
    Stringlower,FileDestX,FileDestX

    return

;------------------------------------------------------------------------------
JustHex(Dec,Length=2)
{
	Hex =
	SetFormat, integer, hex
	Hex += Dec
	Hex := SubStr(Hex, 3)
	StringUpper,Hex,Hex
	If Length = 2
		Hex := Substr("00" . Hex,-1)
	If Length = 4
		Hex := Substr("0000" . Hex,-3)
	If Length = 8
		Hex := Substr("00000000" . Hex,-7)
	SetFormat, integer, d
	Return Hex
}

What am I trying to do ????

So on a Commodore C64, the files that are loaded contain 2 bytes at the start. This is the 16 byte loading address. My AHK script whizzes through a directory full of C64 files and creates documentation (name, length, loading address etc). As I mentioned if the 1st byte >= $7f, then the DLL call worked. Only recently I observed a loading address of $c098 that was documented incorrectly as $c0dc.

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: Joey5 and 337 guests