【发布时间】:2010-05-28 03:35:45
【问题描述】:
我认为我无法使用 Scripting.FileSystemObject 类读取二进制文件。 我可以使用 ADODB.Stream 吗?
还有什么?
我想得到一个字节数组。
谢谢。
【问题讨论】:
标签: javascript wsh
我认为我无法使用 Scripting.FileSystemObject 类读取二进制文件。 我可以使用 ADODB.Stream 吗?
还有什么?
我想得到一个字节数组。
谢谢。
【问题讨论】:
标签: javascript wsh
它还可以将文件作为二进制文件读取,然后使用 VBScript 将返回的对象(变体数组)转换为 Javascript 字节数组。为此,您需要使用 .wsf 文件将 VBScript 和 Javascript 混合在一起。您仍然需要 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>
【讨论】:
我在 codeproject 上查找并找到了 Reading and Writing Binary Files using JScript。
不是我想要的,但非常接近。
它使用 ADODB.Stream 来读取本地文件。显然不可能以一般方式使用 Scripting.FileSystemObject 读取二进制文件,因为无法使用 fso 设置代码页。 fso 始终使用环境代码页,这意味着结果将根据机器的配置而有所不同。 ADODB.Stream 允许程序指定代码页。下一步是将读取的“文本”映射为常规的十六进制字节。这就是上面文章提供的部分。
我成功使用的结果如下。
// 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);
}
})();
而用法是:
var bytes = BinaryFileReader.ReadAllBytes(filename);
【讨论】:
backward 翻译似乎是预设好的。是否有可能以某种方式在运行时构建翻译?
如果您更喜欢带有 COM 对象的纯 jScript,也许我的方法会很有用。它从二进制数据创建一个 jscript 字符串。我更喜欢使用 COM 对象而不是代码页翻译,因为速度快。
//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() 完全一样。
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 的答案有效,并产生了一组数字。另一种方法是将第 5 行替换为
a.push(ts.Read(1));
这会产生一个由单个字符组成的数组,而不是一个数字数组。在我的系统(Windows 7 64 位)上,在循环中一次写入一个字节太慢了,尽管 cheeso 看似等效的读取功能是可以接受的快。在一个Write 中写入一个数组会产生逗号分隔字节。但是由单个字符数组表示的字节可以由函数写入
function WriteByte (File, Byte) {
var Text = "";
for (I = 0; I < Byte.length; I ++) Text += Byte [I];
File.Write (Text);
}
(其中 File 为 ASCII 打开)在我的应用程序中速度可以接受。 (我的系统上的 JavaScript 中有一个错误,如果将包含空字符的字符串传递给函数,则在函数中,字符串的 .length 属性是正确的,但第一个空字符之后的每个字符都是 null(与空字符不同)。但是,在此处引用的函数中,Text 中的空字符得到了正确和快速的管理。)
用字符而不是数字表示字节的另一个优点是每个字节由两个字节而不是四个字节表示。当然,缺点是很多对字节的操作都需要.charCodeAt (0)方法。
【讨论】:
我透露“WindowsInstaller.Installer”可以通过某些参数一一返回真正的字符串字节。因此,您可以将它与“ADODB.Stream”结合使用来访问文件中的真实字节。
然后您也可以使用“SAPI.SpFileStream”ActiveX 对象(俄语:http://forum.script-coding.com/viewtopic.php?id=10092)将它们一个一个或一组写入新文件。这取决于你需要什么。
所有这些 ActiveX 对象都以这种方式正常工作纯 JScript(扩展 JavaScript)任何语言环境,包括中文,预计它们会内置在每个 Windows 中默认为 XP 或 2000。
这是一个示例(您需要将其保存为带有“js”扩展名的文本文件或改用 HTA):
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
我在名为 Resource Extractor 的 HTML 应用程序中使用了这些方法。因此,如果您需要有关如何处理二进制数据的复杂示例,您还可以在https://tastyscriptsforfree.wixsite.com/page/scripts 上查看此应用程序。
【讨论】:
在 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;
}
【讨论】: