Most high-level representations of files are as streams. C's fopen
, ActiveX's Scripting.FileSystemObject
and ADODB.Stream
- in fact, anything built on top of C is very likely to use a stream representation to edit files.
However, when modifying large (~4MiB) fixed-structure binary files, it seems wasteful to read the whole file into memory and write almost exactly the same thing back to disk - this will almost certainly have a performance penalty attached. Looking at the majority of uncompressed filesystems, there seems to me to be no reason why a section of the file couldn't be read from and written to without touching the surrounding data. At a maximum, the block would have to be rewritten, but that's usually on the order of 4KiB; much less than the entire file for large files.
Example:
00 01 02 03
04 05 06 07
08 09 0A 0B
0C 0D 0E 0F
might become:
00 01 02 03
04 F0 F1 F2
F3 F4 F5 0B
0C 0D 0E 0F
A solution using existing ActiveX objects would be ideal, but any way of doing this without having to re-write the entire file would be good.
Okay, here's how to do the exercise in powershell (e.g. hello.ps1
):
$path = "hello.txt"
$bw = New-Object System.IO.BinaryWriter([System.IO.File]::Open($path, [System.IO.FileMode]::Open, [System.IO.FileAccess]::ReadWrite, [System.IO.FileShare]::ReadWrite))
$bw.BaseStream.Seek(5, [System.IO.SeekOrigin]::Begin)
$bw.Write([byte] 0xF0)
$bw.Write([byte] 0xF1)
$bw.Write([byte] 0xF2)
$bw.Write([byte] 0xF3)
$bw.Write([byte] 0xF4)
$bw.Write([byte] 0xF5)
$bw.Close()
You can test it from command line:
powershell -file hello.ps1
Then, you can invoke this from your HTA as:
var wsh = new ActiveXObject("WScript.Shell");
wsh.Run("powershell -file hello.ps1");