The script below starts with calling examples, followed by the functions which could be included in other scripts.
file = c:\z.dat FileDelete %file% IfNotEqual ErrorLevel,0, MsgBox Can't delete file "%file%"`nErrorLevel = "%ErrorLevel%" res := BinWrite(file,"000102030405060708090a0b0c0d0e0f00") MsgBox ErrorLevel = %ErrorLevel%`nBytes Written = %res% res := BinRead(file,data) MsgBox ErrorLevel = %ErrorLevel%`nBytes Read = %res%`nData = "%data%" res := BinWrite(file,"aa00bb",0,2) MsgBox ErrorLevel = %ErrorLevel%`nBytes Written = %res% res := BinRead(file,data) MsgBox ErrorLevel = %ErrorLevel%`nBytes Read = %res%`nData = "%data%" res := BinRead(file,data,3,-2) MsgBox ErrorLevel = %ErrorLevel%`nBytes Read = %res%`nData = "%data%" ExitApp /* ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; BinWrite ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | - Open binary file | - (Over)Write n bytes (n = 0: all) | - From offset (offset < 0: counted from end) | - Close file | data -> file[offset + 0..n-1], rest of file unchanged | Return #bytes actually written */ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; BinWrite(file, data, n=0, offset=0) { ; Open file for WRITE (0x40..), OPEN_ALWAYS (4): creates only if it does not exists h := DllCall("CreateFile","str",file,"Uint",0x40000000,"Uint",0,"UInt",0,"UInt",4,"Uint",0,"UInt",0) IfEqual h,-1, SetEnv, ErrorLevel, -1 IfNotEqual ErrorLevel,0,Return,0 ; couldn't create the file m = 0 ; seek to offset IfLess offset,0, SetEnv,m,2 r := DllCall("SetFilePointerEx","Uint",h,"Int64",offset,"UInt *",p,"Int",m) IfEqual r,0, SetEnv, ErrorLevel, -3 IfNotEqual ErrorLevel,0, { t = %ErrorLevel% ; save ErrorLevel to be returned DllCall("CloseHandle", "Uint", h) ErrorLevel = %t% ; return seek error Return 0 } TotalWritten = 0 m := Ceil(StrLen(data)/2) If (n <= 0 or n > m) n := m Loop %n% { StringLeft c, data, 2 ; extract next byte StringTrimLeft data, data, 2 ; remove used byte c = 0x%c% ; make it number result := DllCall("WriteFile","UInt",h,"UChar *",c,"UInt",1,"UInt *",Written,"UInt",0) TotalWritten += Written ; count written if (!result or Written < 1 or ErrorLevel) break } IfNotEqual ErrorLevel,0, SetEnv,t,%ErrorLevel% h := DllCall("CloseHandle", "Uint", h) IfEqual h,-1, SetEnv, ErrorLevel, -2 IfNotEqual t,,SetEnv, ErrorLevel, %t% Return TotalWritten } /* ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; BinRead ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | - Open binary file | - Read n bytes (n = 0: all) | - From offset (offset < 0: counted from end) | - Close file | data (replaced) <- file[offset + 0..n-1] | Return #bytes actually read */ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; BinRead(file, ByRef data, n=0, offset=0) { h := DllCall("CreateFile","Str",file,"Uint",0x80000000,"Uint",3,"UInt",0,"UInt",3,"Uint",0,"UInt",0) IfEqual h,-1, SetEnv, ErrorLevel, -1 IfNotEqual ErrorLevel,0,Return,0 ; couldn't open the file m = 0 ; seek to offset IfLess offset,0, SetEnv,m,2 r := DllCall("SetFilePointerEx","Uint",h,"Int64",offset,"UInt *",p,"Int",m) IfEqual r,0, SetEnv, ErrorLevel, -3 IfNotEqual ErrorLevel,0, { t = %ErrorLevel% ; save ErrorLevel to be returned DllCall("CloseHandle", "Uint", h) ErrorLevel = %t% ; return seek error Return 0 } TotalRead = 0 data = IfEqual n,0, SetEnv n,0xffffffff ; almost infinite format = %A_FormatInteger% ; save original integer format SetFormat Integer, Hex ; for converting bytes to hex Loop %n% { result := DllCall("ReadFile","UInt",h,"UChar *",c,"UInt",1,"UInt *",Read,"UInt",0) if (!result or Read < 1 or ErrorLevel) break TotalRead += Read ; count read c += 0 ; convert to hex StringTrimLeft c, c, 2 ; remove 0x c = 0%c% ; pad left with 0 StringRight c, c, 2 ; always 2 digits data = %data%%c% ; append 2 hex digits } IfNotEqual ErrorLevel,0, SetEnv,t,%ErrorLevel% h := DllCall("CloseHandle", "Uint", h) IfEqual h,-1, SetEnv, ErrorLevel, -2 IfNotEqual t,,SetEnv, ErrorLevel, %t% SetFormat Integer, %format% ; restore original format Totalread += 0 ; convert to original format Return TotalRead }Edit 2005.07.20: With Chris’ tip I was able to update the functions. Now BinRead can read n characters (all if n = 0) starting from an offset ( offset < 0: counting from the end of the file). It allows, for example, getting MP3 tags or icons from a file, without any external SW.
BinWrite now overwrites n bytes of the file (if it exists) starting from the offset (offset < 0 counting from the end of the file) taken from the beginning of data. If n = 0 all of data is written. It does not change the length of the file unless the written data expands over the original end of file. If the file does not exist, it gets created anew. Un-initialized data could be left in the beginning of a newly created file when non-zero offset is specified. Also, writing at an offset beyond the end of the file also leaves un-initialized data between the old end and the offset.
Edit 2005.07.21: Minor clarifications