什么是在VBA中逐行读取大文件的超快方法?

Jus*_*tin 14 file-io vba

我相信我已经提出了一种非常有效的方法来逐行读取非常非常大的文件.如果您知道更好/更快的方式或者看到改进的空间,请告诉我.我正在努力改进编码,所以你提出的任何建议都会很好.希望这也是其他人可能会觉得有用的东西.

它看起来比我在测试中使用Line Input快8倍.

'This function reads a file into a string.                        '
'I found this in the book Programming Excel with VBA and .NET.    '
Public Function QuickRead(FName As String) As String
    Dim I As Integer
    Dim res As String
    Dim l As Long

    I = FreeFile
    l = FileLen(FName)
    res = Space(l)
    Open FName For Binary Access Read As #I
    Get #I, , res
    Close I
    QuickRead = res
End Function

'This function works like the Line Input statement'
Public Sub QRLineInput( _
    ByRef strFileData As String, _
    ByRef lngFilePosition As Long, _
    ByRef strOutputString, _
    ByRef blnEOF As Boolean _
    )
    On Error GoTo LastLine
    strOutputString = Mid$(strFileData, lngFilePosition, _
        InStr(lngFilePosition, strFileData, vbNewLine) - lngFilePosition)
    lngFilePosition = InStr(lngFilePosition, strFileData, vbNewLine) + 2
    Exit Sub
LastLine:
    blnEOF = True
End Sub

Sub Test()
    Dim strFilePathName As String: strFilePathName = "C:\Fld\File.txt"
    Dim strFile As String
    Dim lngPos As Long
    Dim blnEOF As Boolean
    Dim strFileLine As String

    strFile = QuickRead(strFilePathName) & vbNewLine
    lngPos = 1

    Do Until blnEOF
        Call QRLineInput(strFile, lngPos, strFileLine, blnEOF)
    Loop
End Sub
Run Code Online (Sandbox Code Playgroud)

感谢您的建议!

Rod*_*igo 13

您可以使用Scripting.FileSystemObject来执行该操作.来自参考:

ReadLine方法允许脚本读取文本文件中的各个行.要使用此方法,请打开文本文件,然后设置一个Do循环,该循环一直持续到AtEndOfStream属性为True.(这只是意味着您已到达文件的末尾.)在Do循环中,调用ReadLine方法,将第一行的内容存储在变量中,然后执行某些操作.当脚本循环时,它将自动下拉一行并将文件的第二行读入变量.这将继续,直到读取每一行(或直到脚本专门退出循环).

一个简单的例子:

Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.OpenTextFile("C:\FSO\ServerList.txt", 1)
Do Until objFile.AtEndOfStream
 strLine = objFile.ReadLine
 MsgBox strLine
Loop
objFile.Close
Run Code Online (Sandbox Code Playgroud)

  • 这是另一个有趣的观点.我的(相对有限的)测试表明,这实际上是三者中最慢的方法.使用FSO将文件作为流打开所花费的时间比使用整数文件句柄打开要花费更多的时间,并且将整个文件读取为字符串花费的时间大致相同.当它实际上逐行阅读时它也慢了......如果我没记错的话,无论如何; 自从我完成测试并发布所有这些以来,已经有一段时间了. (3认同)
  • 奇怪的是,这是获得最多支持的答案,因为它忽略了这个问题(有人有*更快的*代码吗?),并盲目地提供最慢的代码作为“答案”(根据其他人的实际测试)。 (3认同)
  • 您是否只测试了文件读取或文件读取和连接?我编写的应用程序使用filesystemobject来加载大文件(超过400MB)并且从不花费太长时间(加载整个文件不超过几秒钟).请记住,除非使用数组实现串联,否则字符串连接总是很慢. (2认同)

Arg*_*gut 11

我的两分钱......

不久前我需要使用VBA读取大文件并注意到这个问题.我测试了从文件中读取数据的三种方法,以比较各种文件大小和行长度的速度和可靠性.方法是:

  1. Line Input VBA声明
  2. 使用文件系统对象(FSO)
  3. Get对整个文件使用VBA语句,然后解析读取的字符串,如此处的帖子所述

每个测试用例包括三个步骤:

  1. 测试用例设置,用于写入包含由已知字符模式填充的给定长度的给定行数的文本文件.
  2. 完整性测试.读取每个文件行并验证其长度和内容.
  3. 文件读取速度测试.重复读取文件的每一行10次.

您可以注意到,步骤#3验证了真正的文件读取速度(如问题中所述),而步骤#2验证文件读取完整性,因此在需要进行字符串解析时模拟真实条件.

下图显示了文件读取速度测试的测试结果.对于所有测试,文件大小为64M字节,并且测试的行长度从2个字节(不包括CRLF)到8M字节不等.

不知道为什么它不再显示:(

结论:

  1. 对于线路正常和异常的大型文件,这三种方法都是可靠的(请与Graeme Howard的答案相比)
  2. 所有这三种方法对于正常线路长度产生几乎相等的文件读取速度
  3. "超快速方式"(方法#3)适用于极长线,而其他两种方法则不行.
  4. 所有这些适用于不同的办公室,不同的PC,适用于VBA和VB6


小智 5

线路输入适用于小文件.但是,当文件大小达到大约90k时,行输入会在整个地方跳转,并从源文件中以错误的顺序读取数据.我用不同的文件大小测试了它:

49k = ok
60k = ok
78k = ok
85k = ok
93k = error
101k = error
127k = error
156k = error
Run Code Online (Sandbox Code Playgroud)

获得的经验教训 - 使用Scripting.FileSystemObject


Nic*_*kis 2

使用该代码,您可以将文件加载到内存中(作为一个大字符串),然后逐行读取该字符串。

通过使用 Mid$() 和 InStr(),您实际上读取了“文件”两次,但由于它在内存中,所以没有问题。
我不知道 VB 的字符串是否有长度限制(可能没有),但如果文本文件的大小为数百兆字节,则由于虚拟内存的使用,可能会出现性能下降。

  • VB 和 VBA 中的**可变长度字符串**的最大长度约为。**20 亿字符**(又名 2GB)。(来源:[VBA](https://msdn.microsoft.com/en-us/vba/language-reference-vba/articles/data-type-summary) 和 [VB](https://learn.microsoft. com/en-us/dotnet/visual-basic/language-reference/data-types/data-type-summary)) (3认同)