一二进制文件在不定位置内含若干"[NOTE]"为首的字符块,现欲提取所有"[NOTE]"及其字节位置,我的算法是:先Dim allNote as String*63536,然后循环取出allNote,再将每个allNote进行arrNote=Split(allNote,"[NOTE]"),可以很快获得"[NOTE]"字符块,之后将各数组arrNote的长度累加作为"[NOTE]"的字节位置,但实际是不对的?因为每个allNote的前几个数组arrNote都会与上一个allNote的后几个数组arrNote的内容重复。我不知错在哪里?请问高手们,除了用字节遍历整个文件,还有什么方法可以解决这个问题?

解决方案 »

  1.   

    二进制文件你用STRING变量来读?
    还是帖代码上来比较清楚。
      

  2.   

    "[NOTE]"是什么编码?一般的说没什么好办法,大致像下面这样:
    Option ExplicitPrivate Sub Command1_Click()
        Dim s As String
        Dim tmp() As Byte
        s = "[NOTE]"
        tmp = StrConv(s, vbFromUnicode)
        Dim mfile As String
        mfile = "你的文件路径"
        Dim buff() As Byte
        Dim i As Long
        i = FileLen(mfile)
        If i < 6 Then Exit Sub
        ReDim buff(i - 1)
        Open mfile For Binary As #1
        Get #1, , buff
        Close #1
        Dim strpos() As Long '用于记录位置
        Dim j As Long
        For i = 0 To UBound(buff) - 5
            If buff(i) = tmp(0) And buff(i + 1) = tmp(1) And buff(i + 2) = tmp(2) And buff(i + 3) = tmp(3) And buff(i + 4) = tmp(4) And buff(i + 5) = tmp(5) Then
                ReDim Preserve strpos(j)
                strpos(j) = i
                j = j + 1
            End If
        Next
    End Sub
      

  3.   

    回2楼,因为用String有个好处就是可以用Split迅速找到分割起点的文本块,用Binary模式读就比较麻烦,反正我的目的是提取二进制文件的文本块(文本块是明文覆盖到一个200Bytes的0字节处的)。我写了一套遍历程序,准确率很高,但实在太慢了,所以到这里找高手们求解。
      

  4.   

    谢谢 rainstormmaster(暴风雨 v2.0) 高手您的代码属于遍历的算法,也很耗时,同时因为"[NOTE]"后面的文本块含有双字节汉字,如"[NOTE]wo shi chengxuyuan.我是程序员.",逐字节判断起来很费力,能不能有其它更好的办法呢?
      

  5.   

    谢谢 rainstormmaster(暴风雨 v2.0) 高手您的代码属于遍历的算法,也很耗时,同时因为"[NOTE]"后面的文本块含有双字节汉字,如"[NOTE]wo shi chengxuyuan.我是程序员.",逐字节判断起来很费力,能不能有其它更好的办法呢?
    -----------------------------
    逐字节判断起来不会很费力,下面的代码应该能执行,但也应该不会比暴风雨的快Private Sub Command1_Click()
        Dim s As String
        s = "[NOTE]"
        
        Dim b() As Byte, temp() As String, TEMP2() As String, pos() As Long
        
        Open "c:\x.txt" For Binary As #1
        ReDim b(LOF(1))
        Get #1, , b
        Close #1
        temp = Split(StrConv(b, vbUnicode), s)
        
        ReDim pos(UBound(temp) - 1)    Dim i As Long
        For i = 0 To UBound(temp) - 1
        TEMP2 = temp
        ReDim Preserve TEMP2(i)
        pos(i) = UBound(StrConv(Join(TEMP2, s), vbFromUnicode)) + 2
        Next
        Erase b
        Erase temp
        Erase TEMP2
        End Sub
      

  6.   

    谢谢 northwolves(狼行天下) 高手呀
    我比较倾向用split获得"[NOTE]"的具体字节位置,但不知为何程序执行到如下一句时报错,说类型不匹配,估计也就是StrConv未能返回正常数组值所致的,调试了一阵,实在没弄明白,只好再再折回来请教northwolves(狼行天下)大师了,拜托了,狼兄出错的位置的代码:pos(i) = UBound(StrConv(Join(TEMP2, s), vbFromUnicode)) + 2
      

  7.   

    //谢谢 northwolves(狼行天下) 高手呀
    我比较倾向用split获得"[NOTE]"的具体字节位置,但不知为何程序执行到如下一句时报错,说类型不匹配你用读字串的方法操作2进制数据(其中含有非字串的内容),会产生不可预料的错误
      

  8.   

    稍改一下:Private Sub Command1_Click()
        Dim s As String
        s = "[NOTE]"
            Dim b() As Byte, temp() As String, TEMP2() As String, pos() As Long
            Open "c:\x.txt" For Binary As #1
        ReDim b(LOF(1))
        Get #1, , b
        Close #1
        temp = Split(StrConv(b, vbUnicode), s)
        Erase b
            ReDim pos(UBound(temp) - 1)
        Dim i As Long
        For i = 0 To UBound(temp) - 1
        TEMP2 = temp
        ReDim Preserve TEMP2(i)
            b = StrConv(IIf(i = 0, TEMP2(0), Join(TEMP2, s)), vbFromUnicode)
        pos(i) = UBound(b) + 2
        Next
        Erase b
        Erase temp
        Erase TEMP2
        End Sub
      

  9.   

    rainstormmaster(暴风雨 v2.0) 
    你用读字串的方法操作2进制数据(其中含有非字串的内容),会产生不可预料的错误
    ==========================
    情况确实是这样,用 northwolves(狼行天下) 提供的代码所抓取的位置还是有些偏差,看来split确实不适宜用来操作二进制数据。奇怪的是:单从速度方面(单个文件测试结果),暴兄的代码还是比狼兄的快2倍左右。谢谢暴兄和狼兄,让我长了不少见识。