line input  不知行不行啊

解决方案 »

  1.   

    line input  太慢。实际上我的行数超过65535,是一个long,
    line input慢慢循环下去实在太慢,这样最后面的行我基本上没法看了
      

  2.   

    你可以考虑这样一个办法:  VB里提供了一个Seek函数和Seek语句。Seek函数是返回当前文件指针的字节位置,而Seek语句是设置文件指针的位置。
      只要你知道第3000行的字节位置,只要一个Seek语句就可以定义到第3000行。但是如何知道第3000行的位置这有点困难。一般的做法是:给你的文件制作一个索引文件,这个索引文件记录着行与字节的对应关系。或者也可以用大数组来实现。不过在更新频繁的情况下就成了问题,生成索引数据需要一定时间。下面是我临时写的一个代码,仅仅说明原理,但是不一定可以运行:Dim tSeekLocates() As LongOpen FileName For Input As #1
      Do
        tStartLine=tStartLine+1 '行号记数
        ReDim Preserve tSeekLocates(tStartLine) '伸长数组
        tSeekLocates(tStartLine)=Seek(1) '记录与行号对应的字节数
        Line Input tReadStr
      Loop Until EOF(1)
    CLose #1根据上面得到的数组tSeekLocates(),假如你想定位到第3000行,只要Seek #1,tSeekLocates(3000)就可以了。
      

  3.   

    以上的办法适合只读不写的场合,只要文件不改变,那么索引数据始终有效。你可以用二进制文件保存该数组。tSeekLocates(0)=UBound(tSeekLocates) '由于不存在第0行,所以用第0行保存数组的长度。Open SeekFileName For Binary As #1
      Put #1,1,tSeekLocates() '写数组到文件。
    Close #1读数组的时候需要先知道数组的长度,也就是第0号元素的值。
    Open SeekFileName For Binary As #1
      Dim tBound As Long
      Get #1,1,tBound '从第一个字节获得数组0号元素的值,也就是数组的长度。
      ReDim tSeekLocates(tBound) '定义数组长度。
      Get #1,1,tSeekLocates() '读数组到文件。
    Close #1以上仅仅是简单的原理,实际上仔细写起来应当用Type定义你自己的结构实现。上面的程序不一定能运行,可能有的地方有些错误,仅仅说明原理。
      

  4.   

    将文件读入,再写入随机方式文件。。如果以随机方式打开文件,Seek返回下一个记录的编号。DimMyRecordAsRecord   '声明变量。
    Open "TESTFILE" For Random As #1
    Len=Len(MyRecord)
    Do While Not EOF(1)    '循环至文件尾。
    Get#1,,MyRecord    '读入下一个记录。
    Debug.PrintSeek(1)   '在立即窗口中显示记录号。
    LoopClose#1   '关闭文件。如果不以Random方式打开文件,则Seek返回下一个操作会发生的位置。
    假设TESTFILE文件内含有文本数据。
    Dim My Char 
    Open"TESTFILE" For Input As #1
    '打开输入文件。Do While Not EOF(1)
    '循环至文件尾。
    MyChar=Input(1,#1)   '读入下一个字符。
    Debug.PrintSeek(1)  '将下一字符的位置显示在立即窗口。
    LoopClose #1      '关闭文件。
      

  5.   

    本示例使用Seek语句在文件内设置下一次读写的位置。
    示例中假设TESTFILE文件内含有用户自定义数据类型Record的记录。
    TypeRecord   '定义用户自定义数据类型。
    ID As Integer
    Name As String*20
    EndType如果以随机方式打开文件,Seek将读写位置设置到下一个记录。
    Dim MyRecord As Record,MaxSize,RecordNumber'声明变量。'以随机文件方式打开文件。
    Open "TESTFILE" For Random As #1 Len=Len(MyRecord)
    MaxSize=LOF(1)\Len(MyRecord)'取得文件中的记录的数。'用循环读入所有记录,但是从最后的记录开始往前读。
    For RecordNumber=MaxSize To 1 Step-1
    Seek#1,RecordNumber  '设置读写位置。
    Get#1,,MyRecord  '读入一个记录。
    Next  RecordNumber
    Close#1
      

  6.   

    好像不行
    1:我这个文件是个LOG文件,在不断不断增加
    2:实际上这个文件现在已经有100M大小,要建立数组也会非常漫长的
    我用过unix下的wc -l,能非常快的得出文件的行数,谁知道它的运算原理??
      

  7.   

    初步给你写了一个函数,并且做了实际的测试,后面有测试结果。不妨尝试一下:Function IndexArrayGetBySourceFile(pFileName As String, Optional pEventON As Boolean = False, Optional pEventLineMax As Long = 100) As Long()
      'IndexArrayGetBySourceFile函数。
      '语法:long tOutIndexs()=IndexArrayGetBySourceFile(pFileName, [pEventON], [pEventLineMax]) As Long()
      '功能:为文本文件建立行号到地址的索引表。
      '参数:string  pFileName     文件名。必须指向一个合法文件。
      '      boolean pEventON      可选参数。响应事件开关。默认为False
      '      long    pEventLineMax 可选参数。响应事件的工作数。默认为100行。
      '返回:long    tOutIndexs()  整形数组。行数对应的数组元素保存有该行的字节地址。
      Dim tOutLongs() As Long
      
      Dim tFileNumber As Integer
      Dim tReadStr As String
      Dim tLineNumber As Long
      Dim tFileSize As Long
      Dim tWorkState As Long
      
      tFileNumber = FreeFile
      tLineNumber = 0
      
      Open pFileName For Input As #tFileNumber
        
        tFileSize = LOF(tFileNumber)
        
        Do
          
          tLineNumber = tLineNumber + 1
          Line Input #tFileNumber, tReadStr
          ReDim Preserve tOutLongs(1 To tLineNumber)
          tOutLongs(tLineNumber) = Seek(tFileNumber)
          
          If Not CBool(tLineNumber Mod pEventLineMax) And pEventON Then
            'tWorkState = tOutLongs(tLineNumber) * 100 \ tFileSize
            'Form1.Text1 = tWorkState
            DoEvents
          End If
        
        Loop Until EOF(tFileNumber)
        
      Close #tFileNumber
      
      IndexArrayGetBySourceFile = tOutLongs()
    End Function
    测试代码:Private Sub Command1_Click()
      Dim tIndexDatas() As Long
      Dim tRndLineNum As Long
      Dim tRndLineAdd As Long
      
      OnTimer = Timer
      tIndexDatas() = IndexArrayGetBySourceFile("ALL.TXT")
      
      tRndLineNum = Int(Rnd * UBound(tIndexDatas)) + 1
      tRndLineAdd = tIndexDatas(tRndLineNum)
      
      Text1.Text = UBound(tIndexDatas) & " Time:" & Timer - OnTimer & " RndLineNum:" & tRndLineNum & " RndLineAdd:" & tRndLineAdd
      Open "ALL.TXT" For Input As #1
        Seek #1, tIndexDatas(tRndLineNum)
        Line Input #1, RdStr
      Close #1
      Text2.Text = RdStr
    End Sub测试结果:ALL.TXT是文本格式的完整《红楼梦》。文件有:24788行消耗时间:0.6599731秒(解释状态,如果编译后能快许多。)随机选择一个行数:17490 
    该行地址:1242374该行的文本:"    脉息. 那王大夫诊了好一回儿,又换那只手也诊了,便同贾琏出来,到外间屋里坐下,"另外,对于我上面说的“补充插入法”,需要一些函数打基础。我会进一步编写出来,你不要着急。假如上面的函数不能令你满意,不妨等我的新函数。
      

  8.   

    另外我还有一个正在研究中的办法叫做“内存定位法”。
      这个方法目前遇到点难题,就是担心字符串能不能承受100M的数据量。原理是这样的:只要你知道第2999个换行的位置,你也就知道了第3000行的位置。而实质上问题就变成了“如何知道一个文件中第N个指定字符的字节位置”。
      初步的实现的办法是先用String将整个文件读到变量里去(这里有个特别快的办法,可以在两个语句的周期搞定)。用Instr函数在该String里寻找第2999个换行,随即得到第3000行的开始。
      由于你的文件特别大,所以我正在研究变通的办法。使这个办法能在100M大文件里可行。  不过,我觉得“Seek定位法”结合“添加补充法更新索引”是解决你这个问题的最佳途径。因为你的文件是只增不减,只追加不插入也不从中间去掉内容。所以特别适合该办法。目前完成了第一步,现在我正在接着写第二步实现索引的更新。