我有一个Web服务加载驱动程序,它是一个Windows脚本文件(WSF),包括一些VBScript和JavaScript文件.我的Web服务要求传入的消息是base64编码的.我目前有一个VBScript函数可以做到这一点,但效率很低(内存密集,主要是由于VBScripts可怕的字符串连接)
[在旁边; 是的,我见过杰夫的最新博文.串联发生在跨越1,000到10,000字节大小的消息的循环中.
我尝试过使用一些自定义字符串连接例程; 一个使用数组,一个使用ADODB.Stream.这些帮助,一点点,但我认为如果我有其他方式编码消息而不是通过我自己的VBS功能,它会有所帮助.
有没有其他方式编码我的消息,优先使用本机Windows方法?
我最初使用的是Antonin Foller的一些VBScript代码: Base64编码VBS功能和Base64解码VBS功能.
在搜索Antonin的网站时,我看到他有一些引用可打印编码的代码,使用CDO.Message对象,所以我试过了.
最后,我移植了Mark对VBScript的回答中提到的代码(也使用了来自这个 SO问题的一些代码),并使用Antonin网站的Stream___StringToBinary和Stream_BinaryToString函数来获取使用MSXML编码的函数.
我运行了一个快速测试来测量所有四种方法中1,500个字符消息的编码时间(我需要发送到我的Web服务的平均消息大小):
原生VBScript(VBScript)
引用Printable,使用CDO.Message(QP)
引用可打印二进制文件,使用CDO.Message(QP Binary)
MSXML/ADODB.Stream(MSXML)
结果如下:
Iterations : 10,000 Message Size : 1,500 +-------------+-----------+ + Method | Time (ms) + +-------------+-----------+ | VBScript | 301,391 | +-------------+-----------+ | QP | 12,922 | +-------------+-----------+ | QP (Binary) | 13,953 | +-------------+-----------+ | MSXML | 3,312 | +-------------+-----------+
我还在测试运行时监视内存利用率(Windows任务管理器中cscript.exe进程的Mem Usage).我没有任何原始数据,但内存利用率均引述打印和MSXML的解决方案是VBScript的解决方案(7,000K对于前者,周围16,000K的VBScript)的下方.
我决定使用MSXML解决方案为我的驱动程序.对于那些感兴趣的人,这是我正在使用的代码:
base64.vbs Function Base64Encode(sText) Dim oXML, oNode Set oXML = CreateObject("Msxml2.DOMDocument.3.0") Set oNode = oXML.CreateElement("base64") oNode.dataType = "bin.base64" oNode.nodeTypedValue =Stream_StringToBinary(sText) Base64Encode = oNode.text Set oNode = Nothing Set oXML = Nothing End Function Function Base64Decode(ByVal vCode) Dim oXML, oNode Set oXML = CreateObject("Msxml2.DOMDocument.3.0") Set oNode = oXML.CreateElement("base64") oNode.dataType = "bin.base64" oNode.text = vCode Base64Decode = Stream_BinaryToString(oNode.nodeTypedValue) Set oNode = Nothing Set oXML = Nothing End Function 'Stream_StringToBinary Function '2003 Antonin Foller, http://www.motobit.com 'Text - string parameter To convert To binary data Function Stream_StringToBinary(Text) Const adTypeText = 2 Const adTypeBinary = 1 'Create Stream object Dim BinaryStream 'As New Stream Set BinaryStream = CreateObject("ADODB.Stream") 'Specify stream type - we want To save text/string data. BinaryStream.Type = adTypeText 'Specify charset For the source text (unicode) data. BinaryStream.CharSet = "us-ascii" 'Open the stream And write text/string data To the object BinaryStream.Open BinaryStream.WriteText Text 'Change stream type To binary BinaryStream.Position = 0 BinaryStream.Type = adTypeBinary 'Ignore first two bytes - sign of BinaryStream.Position = 0 'Open the stream And get binary data from the object Stream_StringToBinary = BinaryStream.Read Set BinaryStream = Nothing End Function 'Stream_BinaryToString Function '2003 Antonin Foller, http://www.motobit.com 'Binary - VT_UI1 | VT_ARRAY data To convert To a string Function Stream_BinaryToString(Binary) Const adTypeText = 2 Const adTypeBinary = 1 'Create Stream object Dim BinaryStream 'As New Stream Set BinaryStream = CreateObject("ADODB.Stream") 'Specify stream type - we want To save binary data. BinaryStream.Type = adTypeBinary 'Open the stream And write binary data To the object BinaryStream.Open BinaryStream.Write Binary 'Change stream type To text/string BinaryStream.Position = 0 BinaryStream.Type = adTypeText 'Specify charset For the output text (unicode) data. BinaryStream.CharSet = "us-ascii" 'Open the stream And get text/string data from the object Stream_BinaryToString = BinaryStream.ReadText Set BinaryStream = Nothing End Function
这个答案改进了Patrick Cuff的优秀答案,因为它增加了对UTF-8和UTF-16 LE编码("Unicode")的支持.(此外,代码也简化了).
例子:
' Base64-encode: from UTF-8-encoded bytes. Base64Encode("Motörhead", False) ' "TW90w7ZyaGVhZA==" ' Base64-encode: from UTF-16 LE-encoded bytes. Base64Encode("Motörhead", True) ' "TQBvAHQA9gByAGgAZQBhAGQA" ' Base64-decode: back to a VBScript string via UTF-8. Base64Decode("TW90w7ZyaGVhZA==", False) ' "Motörhead" ' Base64-decode: back to a VBScript string via UTF-16 LE. Base64Decode("TQBvAHQA9gByAGgAZQBhAGQA", True) ' "Motörhead"
' Base64-encodes the specified string. ' Parameter fAsUtf16LE determines how the input text is encoded at the ' byte level before Base64 encoding is applied. ' * Pass False to use UTF-8 encoding. ' * Pass True to use UTF-16 LE encoding. Function Base64Encode(ByVal sText, ByVal fAsUtf16LE) ' Use an aux. XML document with a Base64-encoded element. ' Assigning the byte stream (array) returned by StrToBytes() to .NodeTypedValue ' automatically performs Base64-encoding, whose result can then be accessed ' as the element's text. With CreateObject("Msxml2.DOMDocument").CreateElement("aux") .DataType = "bin.base64" if fAsUtf16LE then .NodeTypedValue = StrToBytes(sText, "utf-16le", 2) else .NodeTypedValue = StrToBytes(sText, "utf-8", 3) end if Base64Encode = .Text End With End Function ' Decodes the specified Base64-encoded string. ' If the decoded string's original encoding was: ' * UTF-8, pass False for fIsUtf16LE. ' * UTF-16 LE, pass True for fIsUtf16LE. Function Base64Decode(ByVal sBase64EncodedText, ByVal fIsUtf16LE) Dim sTextEncoding if fIsUtf16LE Then sTextEncoding = "utf-16le" Else sTextEncoding = "utf-8" ' Use an aux. XML document with a Base64-encoded element. ' Assigning the encoded text to .Text makes the decoded byte array ' available via .nodeTypedValue, which we can pass to BytesToStr() With CreateObject("Msxml2.DOMDocument").CreateElement("aux") .DataType = "bin.base64" .Text = sBase64EncodedText Base64Decode = BytesToStr(.NodeTypedValue, sTextEncoding) End With End Function ' Returns a binary representation (byte array) of the specified string in ' the specified text encoding, such as "utf-8" or "utf-16le". ' Pass the number of bytes that the encoding's BOM uses as iBomByteCount; ' pass 0 to include the BOM in the output. function StrToBytes(ByVal sText, ByVal sTextEncoding, ByVal iBomByteCount) ' Create a text string with the specified encoding and then ' get its binary (byte array) representation. With CreateObject("ADODB.Stream") ' Create a stream with the specified text encoding... .Type = 2 ' adTypeText .Charset = sTextEncoding .Open .WriteText sText ' ... and convert it to a binary stream to get a byte-array ' representation. .Position = 0 .Type = 1 ' adTypeBinary .Position = iBomByteCount ' skip the BOM StrToBytes = .Read .Close End With end function ' Returns a string that corresponds to the specified byte array, interpreted ' with the specified text encoding, such as "utf-8" or "utf-16le". function BytesToStr(ByVal byteArray, ByVal sTextEncoding) If LCase(sTextEncoding) = "utf-16le" then ' UTF-16 LE happens to be VBScript's internal encoding, so we can ' take a shortcut and use CStr() to directly convert the byte array ' to a string. BytesToStr = CStr(byteArray) Else ' Convert the specified text encoding to a VBScript string. ' Create a binary stream and copy the input byte array to it. With CreateObject("ADODB.Stream") .Type = 1 ' adTypeBinary .Open .Write byteArray ' Now change the type to text, set the encoding, and output the ' result as text. .Position = 0 .Type = 2 ' adTypeText .CharSet = sTextEncoding BytesToStr = .ReadText .Close End With End If end function
所以我还有一些编码器和解码器的完整示例:
编码器:
' This script reads jpg picture named SuperPicture.jpg, converts it to base64 ' code using encoding abilities of MSXml2.DOMDocument object and saves ' the resulting data to encoded.txt file Option Explicit Const fsDoOverwrite = true ' Overwrite file with base64 code Const fsAsASCII = false ' Create base64 code file as ASCII file Const adTypeBinary = 1 ' Binary file is encoded ' Variables for writing base64 code to file Dim objFSO Dim objFileOut ' Variables for encoding Dim objXML Dim objDocElem ' Variable for reading binary picture Dim objStream ' Open data stream from picture Set objStream = CreateObject("ADODB.Stream") objStream.Type = adTypeBinary objStream.Open() objStream.LoadFromFile("SuperPicture.jpg") ' Create XML Document object and root node ' that will contain the data Set objXML = CreateObject("MSXml2.DOMDocument") Set objDocElem = objXML.createElement("Base64Data") objDocElem.dataType = "bin.base64" ' Set binary value objDocElem.nodeTypedValue = objStream.Read() ' Open data stream to base64 code file Set objFSO = CreateObject("Scripting.FileSystemObject") Set objFileOut = objFSO.CreateTextFile("encoded.txt", fsDoOverwrite, fsAsASCII) ' Get base64 value and write to file objFileOut.Write objDocElem.text objFileOut.Close() ' Clean all Set objFSO = Nothing Set objFileOut = Nothing Set objXML = Nothing Set objDocElem = Nothing Set objStream = Nothing
解码器:
' This script reads base64 encoded picture from file named encoded.txt, ' converts it in to back to binary reprisentation using encoding abilities ' of MSXml2.DOMDocument object and saves data to SuperPicture.jpg file Option Explicit Const foForReading = 1 ' Open base 64 code file for reading Const foAsASCII = 0 ' Open base 64 code file as ASCII file Const adSaveCreateOverWrite = 2 ' Mode for ADODB.Stream Const adTypeBinary = 1 ' Binary file is encoded ' Variables for reading base64 code from file Dim objFSO Dim objFileIn Dim objStreamIn ' Variables for decoding Dim objXML Dim objDocElem ' Variable for write binary picture Dim objStream ' Open data stream from base64 code filr Set objFSO = CreateObject("Scripting.FileSystemObject") Set objFileIn = objFSO.GetFile("encoded.txt") Set objStreamIn = objFileIn.OpenAsTextStream(foForReading, foAsASCII) ' Create XML Document object and root node ' that will contain the data Set objXML = CreateObject("MSXml2.DOMDocument") Set objDocElem = objXML.createElement("Base64Data") objDocElem.DataType = "bin.base64" ' Set text value objDocElem.text = objStreamIn.ReadAll() ' Open data stream to picture file Set objStream = CreateObject("ADODB.Stream") objStream.Type = adTypeBinary objStream.Open() ' Get binary value and write to file objStream.Write objDocElem.NodeTypedValue objStream.SaveToFile "SuperPicture.jpg", adSaveCreateOverWrite ' Clean all Set objFSO = Nothing Set objFileIn = Nothing Set objStreamIn = Nothing Set objXML = Nothing Set objDocElem = Nothing Set objStream = Nothing