WinBatch Tech Support Home

Database Search

If you can't find the information using the categories below, post a question over in our WinBatch Tech Support Forum.

TechHome

File Operations

Can't find the information you are looking for here? Then leave a message over on our WinBatch Tech Support Forum.

How to Read Part of File with BinaryRead

Keywords: binaryread  dllcall

Question:

How do I read part of a file into a buffer?

Answer:

Starting in Winbatch 98A, see the function BinaryReadEx.

In earlier versions...There's no way to read just part of a file using the binary functions, but with the new DllCall() function you can do pretty much anything you want (having the Windows SDK documentation helps immensely). Here's an example:

  ;-------------------------------------------------------------------------

  file	  = FileLocate("winbatch.exe")
  ;
  ; "Requires Windows" string
  offset  = 67	; position from BOF/EOF to begin reading (0=first/last byte)
  direct  = 0	; direction to read (0=from beginning of file, 2=from end)
  bufsize = 40	; number of bytes to read
  ;
  ; Copyright notice near end of file
  ;offset  = 528
  ;direct  = 2
  ;bufsize = 41

  ;-------------------------------------------------------------------------

  If direct == 2 Then offset = -(Abs(offset))
  string = StrFill("", bufsize + 1)
  buffer = BinaryAlloc(bufsize + 1)
  hfile = FileOpen(file, "READ")
  dll = DllLoad("krnl386.exe")

  DllCall(dll, word:"_llseek", word:hfile, long:offset, word:direct)
  DllCall(dll, word:"_lread", word:hfile, lpbinary:buffer, word:bufsize)
  string = DllCall(dll, lpstr:"lstrcpy", lpstr:string, lpbinary:buffer)
  DllFree(dll)
  FileClose(hfile)
  BinaryFree(buffer)
  Message("String", string)

Note that the example above cannot be used to get a string which contains a NULL character, because the lstrcpy() function stops when it hits a NULL. I haven't found any way to get a DLL to modify a binary buffer, so I'm returning a string instead. If you need to get a block containing a NULL, you can do so by passing it from the DLL back to WinBatch via a temporary file, like this:

  ;-------------------------------------------------------------------------

  file	  = FileLocate("winbatch.exe")
  ;
  ; Chunk of text strings near end of file
  offset  = 708
  direct  = 2
  bufsize = 275

  ;-------------------------------------------------------------------------

  If direct == 2 Then offset = -(Abs(offset))

  tempfile = "tempfil$.tmp"
  buffer = BinaryAlloc(bufsize + 1)
  hfile = FileOpen(file, "READ")
  htemp = FileOpen(tempfile, "WRITE")
  dll = DllLoad("krnl386.exe")

  DllCall(dll, word:"_llseek", word:hfile, long:offset, word:direct)
  num = DllCall(dll, word:"_lread", word:hfile, lpbinary:buffer, word:bufsize)
  DllCall(dll, word:"_lwrite", word:htemp, lpbinary:buffer, word:num)
  DllFree(dll)
  
  FileClose(hfile)
  FileClose(htemp)
  BinaryRead(buffer, tempfile)
  FileDelete(tempfile)

  ; Now "buffer" contains the chunk of text.  Do what you want with it here.
  BinaryFree(buffer)

This seems a little kludgy, but it works nicely.
Article ID:   W13243
Filename:   Read Part of File with BinaryRead.txt
File Created: 2001:01:03:11:25:20
Last Updated: 2001:01:03:11:25:20