在一个涉及安全的应用中,我需要将一个文件(必须支持任何文件格式)进行电子签名
目前我拿到的安全接口是对一个字符串进行摘要和签名(这点无法改变)
因此,我必须先把文件转换为字符串作为安全函数接口的传入参数
我目前采用的代码是:(我使用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的文件就要花上好几十秒
求高手给个高效率的解决方法,谢谢

解决方案 »

  1.   

    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如果上述过程不能满足你的要求,那么你的代码瓶颈在于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倍也不止。
      

  2.   

    楼上的CopyMemory用的不错,可以把大量的数组字符快速的连成字符串!
      

  3.   

    其实VB的String由于是WUnionCodeChar,因此跟Byte()类型是通用的,换句话说:
    StringData = Space(ByteLength)
    后面可以直接:
    StringData = buff
      

  4.   

    谢谢“songyaowu”的帮助
    对于第二种解决方法,我试演过了,效率问题依旧
    对于第一种解决方法
    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,所以不得不麻烦你解答一下了
      

  5.   

    Dim buff() As Byte直接把buff做为变量引用,就相当于一个字串
      

  6.   

    //我不知道字节流参数在哪里传入估计应该这样调用:
    我假设你已经将文件读出到了byte型数组buff,并且buff数组的下标从0开始
    dim s as string
    s= CreateStringFromByte(varptr(buff(0),ubound(buff)+1)
      

  7.   

    我的意见是采用一些比较成熟的算法,最好是借助于某些组件的功能实现(一般都优化了算法,速度都很快)比如,下面的方法是对文件进行base64,借助了XML3.0:
    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
      

  8.   

    谢谢楼上各位的帮忙,我打算用rainstormmaster(暴风雨 v2.0)提供的XML组件方法