用下面的语句,会造成假死
dim i     as long 
dim j     as long 
dim str   as stringfor i=0 to 60000
    for j=0 to 10
        str=str & "XX" & chr(9)
    next j
    str=str & chr(13)
next i
如何提高速度?

解决方案 »

  1.   

    最终字符串长度 60001 * 11 * 3 + 60001 = 2040034
    Dim i    As Long
    Dim j    As Long
    Dim k    As Long
    Dim str  As String
    str = String(3000000, 0)
    k = 1
    For i = 0 To 6000
        For j = 0 To 10
            Mid$(str, k) = "XX" & Chr(9)
            k = k + 3
        Next j
        Mid$(str, k) = Chr(13)
        k = k + 1
    Next i
    str = Left$(str, k - 1)
    Debug.Print Len(str), k
      

  2.   

    Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
    Dim myString As String, myByte(63989) As ByteMe.MousePointer = vbHourGlassFor i = 0 To 9
        n = i * 3
        myByte(n) = 88 'Asc("X")
        myByte(n + 1) = 88 'Asc("X")
        myByte(n + 2) = IIf(i < 9, 9, 13)
    Next iFor i = 0 To 63989 Step 30
        DoEvents
        CopyMemory myByte(i), myByte(0), 30 
    Next imyString = StrConv(myByte, vbUnicode)
    Me.MousePointer = vbNormal
      

  3.   

    Dim a,b
    Dim y,za = "xx" & Chr(9)
    y = String(11, "a")
    y = Replace(y, "a", a)
    b = y & Chr(13)
    z = String(60000, "b")
    z = Replace(z, "b", b)
      

  4.   

    中间加doevents就不会有假死现象了.但速度不知道怎么让它快起来,关注
      

  5.   

    Private Sub Form_Load()
    Dim i    As Long
    Dim j    As Long
    Dim istr   As String
    Form1.Show
    istr = ""
    For j = 0 To 10
            istr = istr & "XX" & Chr(9)
        Next j
        MsgBox istr
      For i = 0 To 60000 Step 11
        istr = istr & Chr(13)
    Next i
    Print istrEnd Sub
      

  6.   

    用我1楼的代码,将 k 的增量替换成 Len() 取得拼接内容的长度就可以了。
      

  7.   


    假定你的XX放在一个数组 bytSource() 中Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long) 
    Dim myString As String, myByte(63989) As Byte, tmp(29) As Byte 
    Dim i As Long, j As Long, k As LongMe.MousePointer = vbHourGlass
     
    '预先填充制表符和回车符
    For i = 0 To 9 
        n = i * 3 
        tmp(n + 2) = IIf(i < 9, 9, 13) 
    Next i k = 0
    For i = 0 To 63989 Step 30
        DoEvents
        '填充数据到记录 
        For j = 0 To 9
            n = j * 3
            tmp(n) = bytSource(k)
            tmp(n + 1) = bytSource(k + 1)
            k = k + 2
        Next j
        '复制记录
        CopyMemory myByte(i), tmp(0), 30 
    Next i '转换为字符串
    myString = StrConv(myByte, vbUnicode) 
    Me.MousePointer = vbNormal
      

  8.   

    这种操作不如用内存(memset,C中的)操作,或者四个long数据
      

  9.   

    Private Sub Command1_Click()    Dim i As Long
        Dim j As Long
        Dim s As String
        Dim ss As String
        
        For j = 1 To 10
            s = s & "XX" & Chr$(9)
        Next j
        s = s & vbCrLf
        
        ss = s
        For i = 1 To 10
            ss = ss & ss
        Next i
        
        Debug.Print ss
    End Sub
    ;用字符串自己叠加。
      

  10.   

    抛砖引玉,
    这是VB中连接100W个字符“a”最快的代码:先定义一个类型库,在里面声明SysAllocStringByteLen这个API
    module OleAut32
    {
    [entry("SysAllocStringByteLen")]
    BSTR SysAllocStringByteLen ([in] long lpUnicodeString, [in] DWORD Length);
    }
    如果嫌麻烦的话就直接用Declare声明,但效率会下降。Dim str(1000000) As StringOption ExplicitPrivate Declare Function SysAllocStringByteLen Lib "OleAut32" (ByVal lpUnicodeString As Long, ByVal Length As Long) As StringPrivate Sub Form_Load()
        Const SIZE = 1000000    Dim str As String
        Dim buf(SIZE - 1) As Byte
        Dim i As Long
        
        For i = 0 To SIZE - 1
            buf(i) = 97
        Next    str = SysAllocStringByteLen(VarPtr(buf(0)), SIZE)    MsgBox Len(str)
    End Sub
      

  11.   

    上面那句Dim str(1000000) As String没用的。不过Dim buf(SIZE - 1) As Byte倒是应该写在那个位置。因为str是对buf的一个引用。(如果是用类型库的话。用Declare的话Dim buf(SIZE - 1)放在过程内没关系,因为API返回时VB运行时自动把String从FormUnicode转换成Unicode了)
      

  12.   

    如果你要连接的字符串存在于一个字符串数组内,就方便很多了:Option ExplicitPrivate Declare Function GetTickCount Lib "kernel32.dll" () As LongPrivate Const csA As String = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    Private Const StrUbound As Long = 600000        '60W个字符串Private Sub Command1_Click()
        Dim sA As String, sB(StrUbound) As String
        Dim I As Long, J As Long
        
        For I = 0 To StrUbound        '初始化字符串
            sB(I) = csA
        Next
        
        MsgBox "开始"
        
        J = GetTickCount
        sA = Join(sB, vbCrLf)       '用回车换行符来连接
        
        MsgBox "结束,时间=" & GetTickCount - J & "ms"
        
        MsgBox "写入1.txt"
        
        Open "1.txt" For Binary As #1
            Put 1, , sA
        Close #1
        
        MsgBox "结束写入"
    End Sub
    在我这里,60W个字符串的连接花了140毫秒,算快的了,保存得到一个16M的TXT;当改成600W时,花了1034毫秒,不过在保存时就溢出了~~~至于6000W时.......直接就溢出.....这个JOIN很强......之前不知道.....在僵哥那里才知道的,很好很强大吧......VB6里面不知道还有多少不知道的招呢......?
      

  13.   

    随机不定长的拼接现在只有两种方案可行,大家可以写自己的 Test3、Test4……
    Option ExplicitPrivate Const PARTS_COUNT As Long = 100
    Private aParts(PARTS_COUNT - 1) As StringSub Main()
        PrepareParts
        Test1
        Test2
    End Sub'预先准备不定长字符串,减少对拼接速度的影响。可以认为所有的拼接内容是随机的。
    Sub PrepareParts()
        Dim i As Long
        Randomize
        For i = 0 To PARTS_COUNT - 1
            aParts(i) = CStr(Rnd())
        Next
        Debug.Print Len(Join(aParts, "")), Join(aParts, "")
    End SubSub Test1()
        Dim fStart As Single, fFinish As Single
        fStart = Timer()
        '---------------
        Const GROW_SIZE = &H100000 '=1024*1024 = 1M
        Dim i           As Long
        Dim j           As Long
        Dim l           As Long    'Index of aParts
        Dim lLen        As Long    '=Len(aParts(l))
        Dim k           As Long
        Dim kMax        As Long
        Dim str         As String    kMax = GROW_SIZE
        str = String(kMax, 0)    l = 0
        k = 1
        For i = 0 To 60000
            For j = 0 To 10
                lLen = Len(aParts(l))
                If (k + lLen + 1) > kMax Then '<-(1)
                    kMax = kMax + GROW_SIZE
                    str = str & String(kMax, 0)
                End If
                Mid$(str, k) = aParts(l) & vbTab            l = (l + 1) Mod PARTS_COUNT
                k = k + lLen + 1
            Next j
            Mid$(str, k) = vbLf '在 (1) 的增长中多留了一个字符,这里保证够用
            k = k + 1
        Next i
        str = Left$(str, k - 1)    '---------------
        fFinish = Timer()
        Debug.Print "Test1()", FormatNumber(fFinish - fStart, 3), Len(str)
    End SubSub Test2()
        Dim fStart As Single, fFinish As Single
        fStart = Timer()
        '---------------    Dim str         As String
        Dim a()         As String
        Dim i           As Long
        Dim j           As Long
        Dim l           As Long    ReDim a(60001 * 11 - 1)
        For i = 0 To 60000
            For j = 0 To 10
                a(l) = aParts(l Mod PARTS_COUNT) & vbTab
                l = l + 1
            Next
            a(l - 1) = a(l - 1) & vbCr
        Next
        str = Join(a, vbNullString)    '---------------
        fFinish = Timer()
        Debug.Print "Test2()", FormatNumber(fFinish - fStart, 3), Len(str)
    End Sub
      

  14.   

    用VB内置函数的话,join是非常快的,不知道楼主的问题用join和mid语句那个更快?
      

  15.   


    哈哈~~最快的代码应该是这样:Dim str As String
    str = String(SIZE, "a")
    ------------------------
    应该使用数组来操作,就像处理C字符串一样dim i    as long 
    dim j    as long 
    dim str(60000,11)  as string 
    dim str2 as stringfor i=0 to 60000 
        for j=0 to 10
            str(i,j) = "XX" & chr(9) 
        next j 
        str(i,11) = chr(13) 
    next i str2=join(str,"")
      

  16.   


    1. 用API:
       比如定义一个byte数组,然后填充字符,然后调用SysAllocStringByteLen,系统会申请一段全局内存,
       然后,系统把byte数组拷贝到那段内存,返回一个指针(在vb6里是string)   * 花费: 用户总体拷贝1次(一个一个地赋值给byte),系统1次大拷贝2. 用join:
       定义一批string数组,然后你填充字符,然后调用join,系统拷贝这批string数组到另一个连续的byte数组,
       那么byte数组=string1 + string2 + .... ,然后像1那样处理    * 花费: 用户拷贝1次引起系统拷贝多次,像:s(i) = newString ,系统要对s(i)重新分配,然后拷贝newstring给s(i),然后join(s)时,系统会按api方法处理(像方法1那样),所以系统要拷贝2n+1次(2n次小,一次大)3. 直接连接
       花费: 用户拷贝n次,因为像:s(i) = s(i) & newstring , 所以系统每连接一次就要多拷贝1次,1+2+3+...n,
       所以newstring被拷贝n!次,总拷贝数为恐怖次,而且会造成64k缓冲溢出的危险4. 用copymemory:
        这种方法可能最快,比join快在:没有每次对s(i)进行重分配,但会给StrConv拖慢(此函数又总体的拷贝了一次)5. str = String(SIZE, "a")我怀疑是最快的,如果vb6优化的话!!!
       因为:如果直接在申请的byte内存里填充形如:0,0,0,0,0,97,0,97,0,97....,0,0 (unicode字符),
       然后填充一个bstr前缀,不就是一个字符串了吗?? 那么要彻底了解OleAut32!
       
      

  17.   


    更正: 5.   str   =   String(SIZE,   "a ")我怀疑是最快的,如果vb6优化的话!!! 
          因为:如果直接在申请的byte内存里填充形如:0,0,0,0,97,0,97,0,97,0....,0,0   (unicode字符), 
          然后填充一个bstr前缀,不就是一个字符串了吗??   那么要彻底了解OleAut32! 6. mid方法:
       应该比join快,因为mid少一次拷贝(已经预先分配空间),join连接时多拷贝一次
       mid就像copymeory      dim b as byte
         dim i as integer
         b = 97
         i = &H6211
          s = "abcdefg"
         mid(s,3,1) = "a" 
         '或者:copymeory byval strptr(s) + 4, b, 1 'abadefg
         '     copymeory byval strptr(s) + 4, i, 2 'ab我defg      msgbox s  
        
      

  18.   

    在出现Byte数组、copymemory之前,我小时候用过的一种办法。
    Dim i As Long
    Dim j As Long
    Dim str As String
    Dim strx As String
    Dim ie As Long
    Dim iex As Longie = 60000
    iex = Sqr(60000)For i = 0 To ie
      For j = 0 To 10
        strx = strx & "XX" & Chr(9)
      Next j
      strx = strx & Chr(13)
      If Not CBool(i Mod iex) Then
        strx = ""
        str = str & strx
      End If
    Next i
    str = str & strx
      

  19.   

    上面发错了,应该是这样:str = str & strx和strx = ""写颠倒了……
    Dim i As Long
    Dim j As Long
    Dim str As String
    Dim strx As String
    Dim ie As Long
    Dim iex As Long  ie = 60000
      iex = Sqr(60000)  For i = 0 To ie
        For j = 0 To 10
          strx = strx & "XX" & Chr(9)
        Next j
        strx = strx & Chr(13)
        If Not CBool(i Mod iex) Then
          str = str & strx
          strx = ""
        End If
      Next i
      str = str & strx
      
      MsgBox Len(str)
      

  20.   


    小仙妹是VB的天才,恰比当年的比尔·盖茨。希望小仙妹学好汇编,写个操作系统(暂且定名为“Kitesoft Girl”操作系统),再写个在“Kitesoft Girl”下的编译器(暂且定名为“Kitesoft C”),当年比尔·盖茨也只是拿着DOS和BASIC走过来的,我相信以小仙妹的智慧,只要把汇编学好,世界就是你的了!本董是一个艺术家!因为,吹牛是一种艺术!
      

  21.   

    Google 一下 VB 和 StringBuilder 有现成的类可以用