2009-09-28 54 views
0

我正在加速處理一個非常大的文本文件(〜100兆左右)。我謹慎使用redim preserve調用,但仍然需要5分鐘左右才能運行。該文本文件基本上是分析報告,我試圖解析出來。我只能訪問大文件。什麼是一個人要做什麼。 VBA只是慢嗎?這裏是代碼,「報告」對象是我創建的類。大多數報告都只是一個幾百行,所以這就是爲什麼我選擇1000爲UBOUND:用VBA快速處理大文本文件

Public Function GetPages(originalFilePath As String) As Collection 

Dim myReport    As report 
Dim reportPageCollection As Collection 
Dim startLine    As Long 
Dim endLine     As Long 
Dim fso      As FileSystemObject 
Dim file     As textStream 
Dim lineStr     As String 
Dim index     As Long 
Dim lines()     As String 

Set fso = New FileSystemObject 
Set reportPageCollection = New Collection 'initialize the collection 

Set file = fso.OpenTextFile(originalFilePath, ForReading) 

ReDim lines(0 To 1000) 
lineStr = file.ReadLine 'skip the first line so the loop doesnt add a blank report 
lines(0) = lineStr 
index = 1 

Do Until file.AtEndOfLine 'loop through from the startline to find the end line 

    lineStr = file.ReadLine 

      If lineStr Like "1JOBNAME:*" Then 'next report, so we want to return an array of the single line 

        'load this page into our report page collection for further processing 
        Set myReport = New report 
        myReport.setDataLines = lines() 'Fill in 'ReportPage' Array 

        reportPageCollection.Add myReport 'add our report to the collection 

        'set up array for new report 
        ReDim lines(0 To 1000) 
        index = 0 
        lines(index) = lineStr 
        index = index + 1 
      Else 

        '============================ store into array 
         If index = UBound(lines) Then 
          ReDim Preserve lines(0 To UBound(lines) + 1000) 
          lines(index) = lineStr 
          index = index + 1 
         Else 
          lines(index) = lineStr 
          index = index + 1 
         End If 
        '============================ 
      End If 
Loop 

file.Close 
Set fso = Nothing 
Set GetPages = reportPageCollection 

端功能

任何幫助表示讚賞。謝謝!

回答

4

我剛剛從C:\驅動器中抓取了一個73-meg,1.2m行的文本文件。在Excel VBA中逐行讀取整個內容需要6秒鐘(除了閱讀外什麼都不做)。所以速度問題並不明顯與文件IO相關。

幾個意見:

  • 我擔心有一個名爲「文件」變量時文件是腳本運行中的類;
  • Do Until file.AtEndOfLine幾乎立即停止:只要您閱讀一行,您就在行尾。我想你想Do Until file.AtEndOfStream
  • 你的代碼的其餘部分看起來不錯,但我把所有的東西有關添加線陣列整合到方法上的report
  • 是文件實際上就在本地?或者你正在從網絡驅動器讀取數據?這可能解決了這個問題。如果是這樣,請考慮將整個事情讀成一個字符串並將其分開。 100MB並不是那麼大。用我的73MB文件做9秒。
  • 你並不需要創建一個集合變量:GETPAGES已經想成爲該集合

所以你的代碼可能會收縮到這樣的事情:

Public Function GetPages(originalFilePath As String) As Collection 

Dim myReport As report 

Set GetPages = New Collection 'initialize the collection' 

With New FileSystemObject ' no need to store an object' 

    With .OpenTextFile(originalFilePath, ForReading) ' ditto' 

     Set myReport = New report 
     myReport.AddLine .ReadLine 

     Do Until .AtEndOfStream 

      lineStr = file.ReadLine 

      If lineStr Like "1JOBNAME:*" Then 
       GetPages.Add myReport 
       Set myReport = New report 
      End If 

      myReport.AddLine lineStr ' all the array business happens here - much tidier' 

     Loop 
    End With ' TextStream goes out of scope & closes' 
End With ' FileSystemObject goes out of scope, disappears' 

End Function 

有什麼有幫助?

+0

該文件在網絡驅動器上,但我沒有提到我先將其複製到本地驅動器,然後纔開始讀取它。我會試試這個。謝謝! – Fink 2009-09-29 13:38:51

+0

非常棒!對於150兆字節的文件,採用<10秒。不太確定之前爲什麼這麼慢。現在來調整其他功能。 – Fink 2009-09-29 14:09:59

-4

VBA就是這麼慢嗎?

是的。嘗試XLW,一個用於excel的C++包裝器。

0

你可以做一些調整,已知FSO對象比VB本地IO慢。但在這裏我沒有看到任何非常令人討厭的東西。在我們進行微型優化之前,讓我問一個更基本的問題......這些文件恰好在共享驅動器或FTP站點上嗎?如果是這樣,考慮在處理它們之前將它們複製到臨時文件夾。

+0

當你說「已知較慢」時,你有沒有任何參考?我發現情況正好相反。 – 2009-09-29 07:45:32

+0

其共享網絡驅動器,但我在處理之前將其複製到本地計算機。 – Fink 2009-09-29 13:39:31

+0

@Mike我沒有一個方便的鏈接,但它是常識(只是谷歌「FSO是慢」)。這並不是說永遠不要使用FSO。 FSO在編碼時可以節省大量時間,並且完全可以接受各種任務。只是如果你做了非常重的任務,你會開始注意到不同之處。一個典型的例子是迭代硬盤上所有目錄中的所有文件。嘗試使用FSO,然後嘗試使用本機功能(或Win32)。你會注意到實質性的差異。 – Oorang 2009-09-30 05:37:09