【问题标题】:how can I read a binary file with in javascript (Cscript.exe)?如何使用 javascript (Cscript.exe) 读取二进制文件?
【发布时间】:2010-05-28 03:35:45
【问题描述】:

我认为我无法使用 Scripting.FileSystemObject 类读取二进制文件。 我可以使用 ADODB.Stream 吗?

还有什么?

我想得到一个字节数组。

谢谢。

【问题讨论】:

    标签: javascript wsh


    【解决方案1】:

    它还可以将文件作为二进制文件读取,然后使用 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>
    

    【讨论】:

    • 这是要走的路。唯一的解决方案既完整正确。
    • 相反的情况怎么办?即从字节数组到变体。
    【解决方案2】:

    我在 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 翻译似乎是预设好的。是否有可能以某种方式在运行时构建翻译?
    【解决方案3】:

    如果您更喜欢带有 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;
    };
    

    【讨论】:

    • 这似乎与 FSO File.OpenAsTextStream(1).ReadAll() 完全一样。
    【解决方案4】:
    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
    

    来自http://www.ericphelps.com/q193998/index.htm

    【讨论】:

    • 嗯,将其转换为 Javascript 并没有解决问题。问题是从 bin.Read 获得的东西不是 Javascript 字节数组。这是一系列变体。要使用该代码,需要从变量数组映射到 JS 字节数组。查看我的代码stackoverflow.com/questions/2926504/…
    【解决方案5】:

    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)方法。

    【讨论】:

      【解决方案6】:

      我透露“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 上查看此应用程序。

      【讨论】:

      【解决方案7】:

      在 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;
          }
      

      【讨论】:

      • 如何读取二进制并在读取时转换为十六进制?使用您的代码,而不是使用 ADODB.Stream
      • ActiveXObject 已被弃用,仅适用于 IE。即使在某些浏览器中工作,也不应该使用它
      猜你喜欢
      • 2021-12-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-10
      • 2018-12-20
      • 1970-01-01
      • 2019-04-13
      • 2020-11-11
      相关资源
      最近更新 更多