I think I can't read a binary file with the Scripting.FileSystemObject class. Can I do it with ADODB.Stream?
Something else?
I want to get an array of bytes.
thanks.
I think I can't read a binary file with the Scripting.FileSystemObject class. Can I do it with ADODB.Stream?
Something else?
I want to get an array of bytes.
thanks.
I looked and found Reading and Writing Binary Files using JScript on codeproject.
Not quite what I wanted, but pretty close.
It uses ADODB.Stream to read a local file. It's apparently not possible to read a binary file using Scripting.FileSystemObject in a general way, because it's not possible to set the codepage using fso. fso always uses the ambient codepage, which means results will vary depending on the machine's configuration. ADODB.Stream allows the program to specify the codepage. The next step is to map from the "text" read into a regular hex byte. That's the part that the above article provides.
The result I used with success is below.
// BinaryFileReader.js
// ------------------------------------------------------------------
//
// give the ability to read a binary file into an array of bytes,
// to Javascript.
//
// the mapping is based on code from:
// http://www.codeproject.com/KB/scripting/Exsead7.aspx
//
// Created : Fri May 28 05:20:31 2010
// Last-saved : <2010-May-28 06:01:34>
//
// ------------------------------------------------------------------
(function(){
BinaryFileReader = {};
var FileReadTypes = {
adTypeBinary : 1,
adTypeText : 2
};
var backward = [];
backward['C7'] = '80';
backward['FC'] = '81';
backward['E9'] = '82';
backward['E2'] = '83';
backward['E4'] = '84';
backward['E0'] = '85';
backward['E5'] = '86';
backward['E7'] = '87';
backward['EA'] = '88';
backward['EB'] = '89';
backward['E8'] = '8A';
backward['EF'] = '8B';
backward['EE'] = '8C';
backward['EC'] = '8D';
backward['C4'] = '8E';
backward['C5'] = '8F';
backward['C9'] = '90';
backward['E6'] = '91';
backward['C6'] = '92';
backward['F4'] = '93';
backward['F6'] = '94';
backward['F2'] = '95';
backward['FB'] = '96';
backward['F9'] = '97';
backward['FF'] = '98';
backward['D6'] = '99';
backward['DC'] = '9A';
backward['A2'] = '9B';
backward['A3'] = '9C';
backward['A5'] = '9D';
backward['20A7'] = '9E';
backward['192'] = '9F';
backward['E1'] = 'A0';
backward['ED'] = 'A1';
backward['F3'] = 'A2';
backward['FA'] = 'A3';
backward['F1'] = 'A4';
backward['D1'] = 'A5';
backward['AA'] = 'A6';
backward['BA'] = 'A7';
backward['BF'] = 'A8';
backward['2310'] = 'A9';
backward['AC'] = 'AA';
backward['BD'] = 'AB';
backward['BC'] = 'AC';
backward['A1'] = 'AD';
backward['AB'] = 'AE';
backward['BB'] = 'AF';
backward['2591'] = 'B0';
backward['2592'] = 'B1';
backward['2593'] = 'B2';
backward['2502'] = 'B3';
backward['2524'] = 'B4';
backward['2561'] = 'B5';
backward['2562'] = 'B6';
backward['2556'] = 'B7';
backward['2555'] = 'B8';
backward['2563'] = 'B9';
backward['2551'] = 'BA';
backward['2557'] = 'BB';
backward['255D'] = 'BC';
backward['255C'] = 'BD';
backward['255B'] = 'BE';
backward['2510'] = 'BF';
backward['2514'] = 'C0';
backward['2534'] = 'C1';
backward['252C'] = 'C2';
backward['251C'] = 'C3';
backward['2500'] = 'C4';
backward['253C'] = 'C5';
backward['255E'] = 'C6';
backward['255F'] = 'C7';
backward['255A'] = 'C8';
backward['2554'] = 'C9';
backward['2569'] = 'CA';
backward['2566'] = 'CB';
backward['2560'] = 'CC';
backward['2550'] = 'CD';
backward['256C'] = 'CE';
backward['2567'] = 'CF';
backward['2568'] = 'D0';
backward['2564'] = 'D1';
backward['2565'] = 'D2';
backward['2559'] = 'D3';
backward['2558'] = 'D4';
backward['2552'] = 'D5';
backward['2553'] = 'D6';
backward['256B'] = 'D7';
backward['256A'] = 'D8';
backward['2518'] = 'D9';
backward['250C'] = 'DA';
backward['2588'] = 'DB';
backward['2584'] = 'DC';
backward['258C'] = 'DD';
backward['2590'] = 'DE';
backward['2580'] = 'DF';
backward['3B1'] = 'E0';
backward['DF'] = 'E1';
backward['393'] = 'E2';
backward['3C0'] = 'E3';
backward['3A3'] = 'E4';
backward['3C3'] = 'E5';
backward['B5'] = 'E6';
backward['3C4'] = 'E7';
backward['3A6'] = 'E8';
backward['398'] = 'E9';
backward['3A9'] = 'EA';
backward['3B4'] = 'EB';
backward['221E'] = 'EC';
backward['3C6'] = 'ED';
backward['3B5'] = 'EE';
backward['2229'] = 'EF';
backward['2261'] = 'F0';
backward['B1'] = 'F1';
backward['2265'] = 'F2';
backward['2264'] = 'F3';
backward['2320'] = 'F4';
backward['2321'] = 'F5';
backward['F7'] = 'F6';
backward['2248'] = 'F7';
backward['B0'] = 'F8';
backward['2219'] = 'F9';
backward['B7'] = 'FA';
backward['221A'] = 'FB';
backward['207F'] = 'FC';
backward['B2'] = 'FD';
backward['25A0'] = 'FE';
backward['A0'] = 'FF';
var hD="0123456789ABCDEF";
var d2h = function(d)
{
var h = hD.substr(d&15,1);
while(d>15) {d>>>=4;h=hD.substr(d&15,1)+h;}
return h;
}
var h2d = function(h)
{
return parseInt(h,16);
}
var toByteArray = function(inString) {
var encArray = [];
var sL = inString.length;
for (var i=0;i<sL;i++) {
var cc = inString.charCodeAt(i);
if(cc>=128) {
var h = backward[''+d2h(cc)];
cc = h2d(h);
}
encArray.push(cc);
}
return encArray;
}
var _internalReadAll = function(path) {
var bs = WScript.CreateObject("ADODB.Stream")
bs.Type = FileReadTypes.adTypeText;
bs.CharSet = '437';
bs.Open();
bs.LoadFromFile(path);
var what = bs.ReadText;
bs.Close();
return what;
}
BinaryFileReader.ReadAllBytes = function(name)
{
var string = _internalReadAll(name);
return toByteArray(string);
}
})();
And usage is:
var bytes = BinaryFileReader.ReadAllBytes(filename);
It also works to read the file as a binary, and then use VBScript to transform the object that comes back (an array of variant) into a Javascript array of bytes. To do that you need to mix VBScript and Javascript together using a .wsf file. You still need ADODB.Stream.
<job id="Something">
<script id="BFRHelper.vbs" language="VBScript">
Public Function VbBinaryToArray(Binary)
Dim i
ReDim byteArray(LenB(Binary))
For i = 1 To LenB(Binary)
byteArray(i-1) = AscB(MidB(Binary, i, 1))
Next
VbBinaryToArray = byteArray
End Function
</script>
<script language="JavaScript" id="BFR2.js">
(function(){
BinaryFileReader = {};
var FileReadTypes = {
adTypeBinary : 1,
adTypeText : 2
};
BinaryFileReader.ReadAllBytes = function(path)
{
var bs = WScript.CreateObject("ADODB.Stream");
bs.Type = FileReadTypes.adTypeBinary;
bs.Open();
bs.LoadFromFile(path);
var what = bs.Read;
bs.Close();
var array = VbBinaryToArray(what).toArray();
// I find the length property is 1 higher than it ought to be
var aL = array.length;
array.length = aL -1;
return array;
};
})();
var content = BinaryFileReader.ReadAllBytes(path);
</script>
</job>
I looked and found Reading and Writing Binary Files using JScript on codeproject.
Not quite what I wanted, but pretty close.
It uses ADODB.Stream to read a local file. It's apparently not possible to read a binary file using Scripting.FileSystemObject in a general way, because it's not possible to set the codepage using fso. fso always uses the ambient codepage, which means results will vary depending on the machine's configuration. ADODB.Stream allows the program to specify the codepage. The next step is to map from the "text" read into a regular hex byte. That's the part that the above article provides.
The result I used with success is below.
// BinaryFileReader.js
// ------------------------------------------------------------------
//
// give the ability to read a binary file into an array of bytes,
// to Javascript.
//
// the mapping is based on code from:
// http://www.codeproject.com/KB/scripting/Exsead7.aspx
//
// Created : Fri May 28 05:20:31 2010
// Last-saved : <2010-May-28 06:01:34>
//
// ------------------------------------------------------------------
(function(){
BinaryFileReader = {};
var FileReadTypes = {
adTypeBinary : 1,
adTypeText : 2
};
var backward = [];
backward['C7'] = '80';
backward['FC'] = '81';
backward['E9'] = '82';
backward['E2'] = '83';
backward['E4'] = '84';
backward['E0'] = '85';
backward['E5'] = '86';
backward['E7'] = '87';
backward['EA'] = '88';
backward['EB'] = '89';
backward['E8'] = '8A';
backward['EF'] = '8B';
backward['EE'] = '8C';
backward['EC'] = '8D';
backward['C4'] = '8E';
backward['C5'] = '8F';
backward['C9'] = '90';
backward['E6'] = '91';
backward['C6'] = '92';
backward['F4'] = '93';
backward['F6'] = '94';
backward['F2'] = '95';
backward['FB'] = '96';
backward['F9'] = '97';
backward['FF'] = '98';
backward['D6'] = '99';
backward['DC'] = '9A';
backward['A2'] = '9B';
backward['A3'] = '9C';
backward['A5'] = '9D';
backward['20A7'] = '9E';
backward['192'] = '9F';
backward['E1'] = 'A0';
backward['ED'] = 'A1';
backward['F3'] = 'A2';
backward['FA'] = 'A3';
backward['F1'] = 'A4';
backward['D1'] = 'A5';
backward['AA'] = 'A6';
backward['BA'] = 'A7';
backward['BF'] = 'A8';
backward['2310'] = 'A9';
backward['AC'] = 'AA';
backward['BD'] = 'AB';
backward['BC'] = 'AC';
backward['A1'] = 'AD';
backward['AB'] = 'AE';
backward['BB'] = 'AF';
backward['2591'] = 'B0';
backward['2592'] = 'B1';
backward['2593'] = 'B2';
backward['2502'] = 'B3';
backward['2524'] = 'B4';
backward['2561'] = 'B5';
backward['2562'] = 'B6';
backward['2556'] = 'B7';
backward['2555'] = 'B8';
backward['2563'] = 'B9';
backward['2551'] = 'BA';
backward['2557'] = 'BB';
backward['255D'] = 'BC';
backward['255C'] = 'BD';
backward['255B'] = 'BE';
backward['2510'] = 'BF';
backward['2514'] = 'C0';
backward['2534'] = 'C1';
backward['252C'] = 'C2';
backward['251C'] = 'C3';
backward['2500'] = 'C4';
backward['253C'] = 'C5';
backward['255E'] = 'C6';
backward['255F'] = 'C7';
backward['255A'] = 'C8';
backward['2554'] = 'C9';
backward['2569'] = 'CA';
backward['2566'] = 'CB';
backward['2560'] = 'CC';
backward['2550'] = 'CD';
backward['256C'] = 'CE';
backward['2567'] = 'CF';
backward['2568'] = 'D0';
backward['2564'] = 'D1';
backward['2565'] = 'D2';
backward['2559'] = 'D3';
backward['2558'] = 'D4';
backward['2552'] = 'D5';
backward['2553'] = 'D6';
backward['256B'] = 'D7';
backward['256A'] = 'D8';
backward['2518'] = 'D9';
backward['250C'] = 'DA';
backward['2588'] = 'DB';
backward['2584'] = 'DC';
backward['258C'] = 'DD';
backward['2590'] = 'DE';
backward['2580'] = 'DF';
backward['3B1'] = 'E0';
backward['DF'] = 'E1';
backward['393'] = 'E2';
backward['3C0'] = 'E3';
backward['3A3'] = 'E4';
backward['3C3'] = 'E5';
backward['B5'] = 'E6';
backward['3C4'] = 'E7';
backward['3A6'] = 'E8';
backward['398'] = 'E9';
backward['3A9'] = 'EA';
backward['3B4'] = 'EB';
backward['221E'] = 'EC';
backward['3C6'] = 'ED';
backward['3B5'] = 'EE';
backward['2229'] = 'EF';
backward['2261'] = 'F0';
backward['B1'] = 'F1';
backward['2265'] = 'F2';
backward['2264'] = 'F3';
backward['2320'] = 'F4';
backward['2321'] = 'F5';
backward['F7'] = 'F6';
backward['2248'] = 'F7';
backward['B0'] = 'F8';
backward['2219'] = 'F9';
backward['B7'] = 'FA';
backward['221A'] = 'FB';
backward['207F'] = 'FC';
backward['B2'] = 'FD';
backward['25A0'] = 'FE';
backward['A0'] = 'FF';
var hD="0123456789ABCDEF";
var d2h = function(d)
{
var h = hD.substr(d&15,1);
while(d>15) {d>>>=4;h=hD.substr(d&15,1)+h;}
return h;
}
var h2d = function(h)
{
return parseInt(h,16);
}
var toByteArray = function(inString) {
var encArray = [];
var sL = inString.length;
for (var i=0;i<sL;i++) {
var cc = inString.charCodeAt(i);
if(cc>=128) {
var h = backward[''+d2h(cc)];
cc = h2d(h);
}
encArray.push(cc);
}
return encArray;
}
var _internalReadAll = function(path) {
var bs = WScript.CreateObject("ADODB.Stream")
bs.Type = FileReadTypes.adTypeText;
bs.CharSet = '437';
bs.Open();
bs.LoadFromFile(path);
var what = bs.ReadText;
bs.Close();
return what;
}
BinaryFileReader.ReadAllBytes = function(name)
{
var string = _internalReadAll(name);
return toByteArray(string);
}
})();
And usage is:
var bytes = BinaryFileReader.ReadAllBytes(filename);
backward
translation seems pre-set. Is it possible to costruct the translation at run-time somehow? –
Slack If you prefer pure jScript with COM objects, maybe my method could be useful. It creates a jscript string from binary data. I prefer to use COM objects instead code page translations because speed.
//Reads a binary file, returns a string
function binaryFileToString(fileName) {
var binStream = new ActiveXObject("ADODB.Stream");
var fs = new ActiveXObject("Scripting.FileSystemObject");
var size = (fs.getFile(fileName)).size;
binStream.Type = 1; //adTypeBinary
binStream.Open;
binStream.loadFromFile(fileName);
var binVariant = binStream.read();
var adLongVarChar = 201;
var RS = new ActiveXObject("ADODB.Recordset");
RS.fields.append("mBinary", adLongVarChar, size);
RS.open();
RS.addNew();
RS("mBinary").appendChunk(binVariant);
RS.update();
return RS("mBinary").value;
};
File.OpenAsTextStream(1).ReadAll()
. –
Slack Function ReadByteArray(strFileName)
Const adTypeBinary = 1
Dim bin
Set bin = CreateObject("ADODB.Stream")
bin.Type = adTypeBinary
bin.Open
bin.LoadFromFile strFileName
ReadByteArray = bin.Read
End Function
Cheeso’s answer works, and yields an array of numbers. An alternative is to replace line 5 with
a.push(ts.Read(1));
This yields an array of single characters instead of an array of numbers. On my system (Windows 7 64-bit), writing the bytes one at a time in a loop is too slow, even though cheeso’s seemingly equivalent reading function is acceptably fast. Writing an array in one Write
yields commas separating the bytes. But bytes represented by an array of single characters can be written by the function
function WriteByte (File, Byte) {
var Text = "";
for (I = 0; I < Byte.length; I ++) Text += Byte [I];
File.Write (Text);
}
(in which File
is opened for ASCII) which is acceptably fast in my application. (There is a bug in JavaScript on my system that, if a string containing null characters is passed to a function, in the function the .length
property of the string is correct but every character after the first null character is null
(as distinct from the null character). However, in the here-cited function, null characters in Text
are managed correctly as well as expeditiously.)
Another advantage of representing bytes by characters instead of numbers is that each byte is represented by two bytes instead of four. Of course, the disadvantage is that many operations on the bytes require the .charCodeAt (0)
method.
I revealed that the "WindowsInstaller.Installer" can return true string bytes one by one with certain parameters passed. So you can use it in combination with "ADODB.Stream" to access true bytes from file.
Then you can also write them into new file one by one or in a bunch by using "SAPI.SpFileStream" ActiveX object (in Russian: http://forum.script-coding.com/viewtopic.php?id=10092). It depends on what you need.
All these ActiveX objects work fine this way in pure JScript (extended JavaScript) on any locale including Chinese and it is expected they are built-in in every Windows since XP or 2000 by default.
Here is a sample (you need to save it as a text file with "js" extension or use HTA instead):
var doc = GetObject('\\', 'htmlfile');
doc.write("<xml><_ xmlns:dt='urn:schemas-microsoft-com:datatypes'><_ dt:dt='bin.hex'/></_></xml>");
var xml = doc.documentElement.firstChild.children[1];
xml.preserveWhiteSpace = 1;
var hex = xml.firstChild.childNodes[0],
bytesToHex = function(bytes) //convert true bytes to hex string
{
hex.nodeTypedValue = bytes;
return hex.text;
},
hexToBytes = function(hString) //convert hex string to true bytes
{
hex.text = hString;
return hex.nodeTypedValue;
},
source = new ActiveXObject('WindowsInstaller.Installer').CreateRecord(1), //source file stream
memory = new ActiveXObject('ADODB.Stream'), //memory stream
output = new ActiveXObject('SAPI.SpFileStream'), //output file stream
sourceRead = function(bytesCount) //read true bytes from source file stream starting from its previous position
{
memory.Position = 0;
memory.Type = 2; //adTypeText = 2
memory.Charset = 'Unicode';
memory.WriteText(source.ReadStream(1, bytesCount, 3)); //msiReadStreamDirect = 3
memory.SetEOS();
memory.Position = 0;
memory.Type = 1; //adTypeBinary = 1
memory.Position = 2; //skip "BOM" header
return memory.Read(bytesCount);
}
source.SetStream(1, 'C:\\Windows\\System32\\shell32.dll'); //open source file stream for reading
memory.Open(); //open memory stream for reading and writing
output.Format.Type = 1; //SAFTText = 1
output.Open('your output path goes here.bin', 3); //create and open output file for writing (SSFMCreateForWrite = 3)
var arrayOfTrueBytes = [],
arrayOfHexBytes = [],
trueByte;
for(var i = 0; i < 7; i ++) //fill arrays with first 7 bytes of source file stream one by one
{
trueByte = sourceRead(1);
arrayOfTrueBytes[i] = trueByte;
arrayOfHexBytes[i] = bytesToHex(trueByte);
}
doc.parentWindow.alert(arrayOfHexBytes); //show hex representation of true bytes in array
for(var i = 0; i < 7; i ++)
output.Write(arrayOfTrueBytes[i]); //write true bytes one by one from array to output file stream
output.Write(sourceRead(10)); //write a bunch of next 10 true bytes of source file stream to output file stream
output.Write('\u3231\x20'); //write string bytes to output file stream
output.Write(hexToBytes('68656c6c6f')); //write true bytes converted from hex string to output file stream
I used these approaches in my HTML application called Resource Extractor. So if you need complex samples on how to work with binary data you can also check this application at https://tastyscriptsforfree.wixsite.com/page/scripts.
Read the bytes of a file, in jscript.
function readAllBytes(path) {
var fso = new ActiveXObject("Scripting.FileSystemObject"),
ts = fso.OpenTextFile(path, 1), a = [];
while (!ts.AtEndOfStream)
a.push(ts.Read(1).charCodeAt(0));
ts.Close();
return a;
}
© 2022 - 2024 — McMap. All rights reserved.
backward
translation seems pre-set. Is it possible to costruct the translation at run-time somehow? – Slack