I have noticed that NETLink
does not get a lot of love on this site (at least not as much as JLink
does), so let me just post this solution based on NETLink
. Note that you can use NETLink
on any of the popular Operating Systems out there (.NET platform is also now open source), but if you're on Windows, NETLink
is highly preferred to JLink
. Anyhow, here is the code:
Needs["NETLink`"]
InstallNET[];
editBinary[file_String?FileExistsQ, pos : {{_, _} ..}] := NETBlock[
Module[{str},
LoadNETType /@ {"System.IO.FileMode", "System.IO.FileAccess"};
str = NETNew["System.IO.FileStream", file, FileMode`Open,
FileAccess`ReadWrite];
Scan[(str @ Position = #[[1]]; str @ WriteByte[#[[2]]]) &, pos];
str @ Close[]
]
]
Usage:
bfile = "C:\\Path\\To\\Your\\file";
editBinary[bfile, {{1, 65}, {5, 86}}]
The first element in each input list is the position at which the data is to be replaced while the second item in each list is the corresponding data to be written.
For those that like terser code, here is a shorter version that replaces the Enums
with their corresponding integer values, hence, no need to load their types:
editBinary[file_String?FileExistsQ, pos : {{_, _} ..}] :=
Module[{str},
str = NETNew["System.IO.FileStream", file, 3, 3];
Scan[(str @ Position = #[[1]]; str @ WriteByte[#[[2]]]) &, pos];
str @ Close[]
]
Usage is same as before.
SetStreamPosition
andBinaryWrite
combined should be able to perform this task. The problem is that Mathematica will not allow you to simultaneously use these functions, because a file opened withOpenWrite
is treated as empty, and a file opened withOpenAppend
does not supportSetStreamPosition
. AFAIK there is no other way to open a file for writing. $\endgroup$f = OpenAppend["bigFile.dat"]; SetStreamPosition[f, 0]
returns$Failed
and issues the warning messageSetStreamPosition::openw: OutputStream[...] is open for output.
Like I said,OpenAppend
does not supportSetStreamPosition
. $\endgroup$