Jump to content

Workaround For Reading And Writing Binary Files


sugi
 Share

Recommended Posts

While reading severall posts about binary data and the problem with the \0-character in strings I remembered a different way to store the data in AutoIt: using hexadecimal values. Of course this has a major drawback: It takes two times the memory the binary data would have taken. Also reading them is very slow, since every single byte has to be read separate.

When we come to writing there's a big problem: AutoIt itself cannot write \0-characters. Therefore I'm using debug.exe (ships with every windows version I know) for writing the data back to the file. But debug.exe has one real hard drawback: It only supports a filesize of up to 65535 byte as far as I know. So if you need to write bigger files you'd first have to write them in chunks small enough for debug.exe and then use the dos command copy /b file1.bin+file2.bin result.bin to concatenate them together.

I've written these two functions as a proof of concept because I don't have a need for this but thought I'd share the idea. This means I've done only basic tests with a 5 byte file and a 511 byte file and it worked for them. If you want to use these function I suggest you do some more tests. Also the temporary filenames are hardcoded, you might want to change them to a better name (autoit3.tmp and autoit3.dbg)

The last two lines demonstrate the use.

Func FileReadBinFile($Filename)
   Dim $File, $Binarydata='', $length=0, $read, $counter
  ; Open the file
   $File = FileOpen($Filename, 0)
   If $File = -1 Then
      SetError(1)
      Return 0
   EndIf
   
  ; Run in a loop to read the data
   $read=FileRead($File, 1)
   While not @error
      If ($length +2) > 2147483647 Then
         FileClose($File)
         SetError(2)
         Return $Binarydata
      EndIf
      $Binarydata = $Binarydata & Hex(Asc($read), 2)
      $length = $length + 2
      $read=FileRead($File, 1)
   Wend
   FileClose($File)
   SetError(0)
   Return $Binarydata
EndFunc

Func FileWriteBinFile($Filename, ByRef $Binarydata)
   Dim $File, $TMPFile=@TempDir & '\autoit3.dbg', $TotalBytes=StringLen($Binarydata)/2, $Line, $Bytecounter
  ; Debug only seems to support up to 65535 byte
   If $TotalBytes > 65535 Then
      SetError(1)
      Return 0
   EndIf
   $File = FileOpen($TMPFile, 2)
   If $File = -1 Then
      SetError(2)
      Return 0
   EndIf
   
  ; Write data to file
   For $Bytecounter = 1 to $TotalBytes Step 0
      $Line = 'e ' & Hex($Bytecounter + 255, 4)
      For $Bytecounter = $Bytecounter to $Bytecounter + 15
         If $Bytecounter > $Totalbytes Then ExitLoop
         $Line = $Line & ' ' & StringMid($Binarydata, $Bytecounter*2-1, 2)
      Next
      FileWriteLine($File, $Line)
   Next
   FileWriteLine($File, 'r cx')
   FileWriteLine($File, Hex($TotalBytes, 4))
   FileWriteLine($File, 'n autoit3.tmp')
   FileWriteLine($File, 'w')
   FileWriteLine($File, 'q')
   FileClose($File)
   RunWait(@ComSpec & ' /c debug < autoit3.dbg', @TempDir, @SW_HIDE)
   FileDelete(@TempDir & '\autoit3.dbg')
   FileMove(@TempDir & '\autoit3.tmp', $Filename, 1)
EndFunc

$Bin = FileReadBinFile('senvar.com')
FileWriteBinFile('test2.txt', $Bin)
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...