在一个涉及安全的应用中,我需要将一个文件(必须支持任何文件格式)进行电子签名
目前我拿到的安全接口是对一个字符串进行摘要和签名(这点无法改变)
因此,我必须先把文件转换为字符串作为安全函数接口的传入参数
我目前采用的代码是:(我使用VB 6.0)
文件->Byte:
Dim mfile As String
mfile = FileDialog1.FileName
Dim buff() As Byte
Dim i As Long
i = FileLen(mfile)
If i = 0 Then Exit Sub
ReDim buff(i - 1)
Open mfile For Binary As #1
Get #1, , buff
Close #1文件->字符串:
Public Function BinaryToString(ByVal BinaryStr As Variant) As String '二进制转换为字符串
Dim lnglen As Long
Dim tmpBin As Variant
Dim strC As String
Dim skipflag As Long
Dim i As Long
skipflag = 0
strC = ""
If Not IsNull(BinaryStr) Then
lnglen = LenB(BinaryStr)
MsgBox ("lnglen=" & lnglen)
For i = 1 To lnglen
If skipflag = 0 Then
tmpBin = MidB(BinaryStr, i, 1)
If AscB(tmpBin) > 127 Then
'strC = strC & Chr(AscW(MidB(BinaryStr, i + 1, 1) & tmpBin))
'skipflag = 1
Else
'strC = strC & Chr(AscB(tmpBin))
End If
Else
skipflag = 0
End If
Next
End If
BinaryToString = strC
End Function结果运行下来,发现效率非常慢,一个几十K的文件就要花上好几十秒
求高手给个高效率的解决方法,谢谢
目前我拿到的安全接口是对一个字符串进行摘要和签名(这点无法改变)
因此,我必须先把文件转换为字符串作为安全函数接口的传入参数
我目前采用的代码是:(我使用VB 6.0)
文件->Byte:
Dim mfile As String
mfile = FileDialog1.FileName
Dim buff() As Byte
Dim i As Long
i = FileLen(mfile)
If i = 0 Then Exit Sub
ReDim buff(i - 1)
Open mfile For Binary As #1
Get #1, , buff
Close #1文件->字符串:
Public Function BinaryToString(ByVal BinaryStr As Variant) As String '二进制转换为字符串
Dim lnglen As Long
Dim tmpBin As Variant
Dim strC As String
Dim skipflag As Long
Dim i As Long
skipflag = 0
strC = ""
If Not IsNull(BinaryStr) Then
lnglen = LenB(BinaryStr)
MsgBox ("lnglen=" & lnglen)
For i = 1 To lnglen
If skipflag = 0 Then
tmpBin = MidB(BinaryStr, i, 1)
If AscB(tmpBin) > 127 Then
'strC = strC & Chr(AscW(MidB(BinaryStr, i + 1, 1) & tmpBin))
'skipflag = 1
Else
'strC = strC & Chr(AscB(tmpBin))
End If
Else
skipflag = 0
End If
Next
End If
BinaryToString = strC
End Function结果运行下来,发现效率非常慢,一个几十K的文件就要花上好几十秒
求高手给个高效率的解决方法,谢谢
'**********************************
' 字节数组中的数据连接成字符串
'**********************************
Private Function CreateStringFromByte(p As Long, ByteLength As Long) As String
Dim StringData As String
'** 分配字符串空间
StringData = Space(ByteLength)
'** 复制字符数组地址内容到字符串地址
CopyMemory ByVal StringData, ByVal p, ByteLength
'** 返回字符串
CreateStringFromByte = StringData
End Function如果上述过程不能满足你的要求,那么你的代码瓶颈在于For中的
'strC = strC & Chr(AscW(MidB(BinaryStr, i + 1, 1) & tmpBin))
'strC = strC & Chr(AscB(tmpBin))
两句,解决方案大致如下:
dim strC() as string
dim strCS as stringlnglen = LenB(BinaryStr)
redim strC(lnglen-1)
j=0
For i = 1 To lnglen
If skipflag = 0 Then
tmpBin = MidB(BinaryStr, i, 1)
If AscB(tmpBin) > 127 Then
strC(j) = Chr(AscW(MidB(BinaryStr, i + 1, 1) & tmpBin))
'skipflag = 1
j=j+1
Else
strC(j) = Chr(AscB(tmpBin))
j=j+1
End If
Else
skipflag = 0
End If
NextstrCS = join (strC())如果文件很大,那么建议不要一次分配所有文件长度的strC数组,可以分配较小的空间,然后再分次连接,我试过对一个文件做载入测试,对于100K的文件,此法比&运算要快上1000倍也不止。
StringData = Space(ByteLength)
后面可以直接:
StringData = buff
对于第二种解决方法,我试演过了,效率问题依旧
对于第一种解决方法
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
'**********************************
' 字节数组中的数据连接成字符串
'**********************************
Private Function CreateStringFromByte(p As Long, ByteLength As Long) As String
Dim StringData As String
'** 分配字符串空间
StringData = Space(ByteLength)
'** 复制字符数组地址内容到字符串地址
CopyMemory ByVal StringData, ByVal p, ByteLength
'** 返回字符串
CreateStringFromByte = StringData
End Function我不知道字节流参数在哪里传入
我平时几乎没碰过VB,一直是开发Java,只是那个破安全的摘要COM接口不支持文件名传入,害得我不得不去摸VB,所以不得不麻烦你解答一下了
我假设你已经将文件读出到了byte型数组buff,并且buff数组的下标从0开始
dim s as string
s= CreateStringFromByte(varptr(buff(0),ubound(buff)+1)
Option Explicit'需要引用Microsoft XML, v3.0
Private Function Encode(iArray() As Byte) As String '编码
Dim iXml As New MSXML2.DOMDocument30
With iXml.createElement("Encoder")
.dataType = "bin.base64"
.nodeTypedValue = iArray()
Encode = .Text
End With
End Function
Private Function Decode(ByVal iStrbase64 As String) As Byte() '解码
Dim strXML As String
strXML = "<DECODER xmlns:dt=" & Chr(34) & "urn:schemas-microsoft-com:datatypes" & Chr(34) & " dt:dt=" & Chr(34) & "bin.base64" & Chr(34) & ">" & iStrbase64 & "</DECODER>"
With New MSXML2.DOMDocument30
.loadXML strXML
Decode = .selectSingleNode("DECODER").nodeTypedValue
End With
End Function