-1

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.

wizzwizz4
  • 6,140
  • 2
  • 26
  • 62
  • Could you update your question to include attempted code snippets? Also, is hta / javascript an absolute must. If you're flexible with the technology, have you considered PowerShell? http://stackoverflow.com/questions/20935356/methods-to-hex-edit-binary-files-via-powershell – Stephen Quan Oct 18 '15 at 23:12
  • @StephenQuan I mean a non-stream based file management approach. I don't know how to do that in C, and have been told it's impossible in Python... It might not be possible! The link you gave just opens a file then saves a modified copy, writing all the unchanged bytes again... I want a way to only touch the modified bytes, for speed reasons. – wizzwizz4 Oct 19 '15 at 17:47
  • BTW, I'm not the one downvoting your question, I would like to know why people think it's a bad question too, since, I think it's a legitimate question myself. I think the PowerShell is still a valid way to go. You can still use HTA as your frontend UI and do something along the lines of: http://stackoverflow.com/questions/20935356/methods-to-hex-edit-binary-files-via-powershell – Stephen Quan Oct 20 '15 at 05:21
  • @StephenQuan Yes but... Ok. Imagine I'm dealing with a 500GB file, and I need to change 273 bytes, all scattered around the file. It would take a long time to read and write the entire file again, just for those 273 bytes. So I'm looking for a way to edit the bytes in a 'really low level' way, instead of reading from stream A and writing to stream B (high level stuff)! – wizzwizz4 Oct 20 '15 at 16:40
  • in my case, if I was faced with this issue, I'd contemplate building my own ActiveX library. Having said that, there is probably something you can download, but, I suspect you're going for a zero-install footprint to achieve your goal? – Stephen Quan Oct 20 '15 at 23:56
  • @StephenQuan How do you write ActiveX libraries for XP? – wizzwizz4 Oct 21 '15 at 16:51
  • Sorry, Win7! Just realised they'd updated their system. – wizzwizz4 Oct 21 '15 at 18:00
  • Making your own ActiveX library would involve Visual Studio and knowledge in either C++ or .NET. The result is a .DLL which must be registered with the OS with regsvr32. I suspect this may be too much to ask. Alternatively, I did come up with a theoretically hybrid solution that is exclusively HTA -> Powershell and doesn't require any ActiveX but, I will need to find some spare time to prove the answer to myself. – Stephen Quan Oct 22 '15 at 22:39

1 Answers1

2

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");
Stephen Quan
  • 21,481
  • 4
  • 88
  • 75