【问题标题】:Read Number of lines in Large Text File VB6读取大文本文件 VB6 中的行数
【发布时间】:2017-12-18 23:36:47
【问题描述】:

我有大小为 230MB 的文本文件。我想计算该文件的行数。

我尝试了“Scripting.FileSystemOblect”,但内存不足。

请帮忙。

谢谢。

【问题讨论】:

  • UBound 至少从 QBasic 开始就受到支持

标签: vba text vb6


【解决方案1】:

正常的 Windows 换行符是 CRLF,因此您可以计算 LF 并在文件的最后一行后面没有 1 的情况下将计数加 1。

在真正的 VB(即 VB5、VB6 等)中,您可以利用面向字节的字符串操作来加速许多任务。如果我们可以假设文本文件包含 ANSI,那么这非常快:

Option Explicit

Private Sub Main()
    Const BUFSIZE As Long = 100000
    Dim T0 As Single
    Dim LfAnsi As String
    Dim F As Integer
    Dim FileBytes As Long
    Dim BytesLeft As Long
    Dim Buffer() As Byte
    Dim strBuffer As String
    Dim BufPos As Long
    Dim LineCount As Long

    T0 = Timer()
    LfAnsi = StrConv(vbLf, vbFromUnicode)
    F = FreeFile(0)
    Open "big.txt" For Binary Access Read As #F
    FileBytes = LOF(F)
    ReDim Buffer(BUFSIZE - 1)
    BytesLeft = FileBytes
    Do Until BytesLeft = 0
        If BufPos = 0 Then
            If BytesLeft < BUFSIZE Then ReDim Buffer(BytesLeft - 1)
            Get #F, , Buffer
            strBuffer = Buffer 'Binary copy of bytes.
            BytesLeft = BytesLeft - LenB(strBuffer)
            BufPos = 1
        End If
        Do Until BufPos = 0
            BufPos = InStrB(BufPos, strBuffer, LfAnsi)
            If BufPos > 0 Then
                LineCount = LineCount + 1
                BufPos = BufPos + 1
            End If
        Loop
    Loop
    Close #F
    'Add 1 to LineCount if last line of your files do not
    'have a trailing CrLf.
    MsgBox "Counted " & Format$(LineCount, "#,##0") & " lines in" & vbNewLine _
         & Format$(FileBytes, "#,##0") & " bytes of text." & vbNewLine _
         & Format$(Timer() - T0, "0.0#") & " seconds."
End Sub

给定一个 293MB 的 7,000,000 行文件,这里只需要 0.7 秒。但请注意,我没有重新启动以确保在运行该测试时文件没有被缓存。如果没有缓存(即重启后),我预计它需要 5 倍的时间。

转换为处理 Unicode 文本文件相当简单。只需将 B 函数替换为非 B 等效项,确保将 BUFSIZE 设置为 2 的倍数,然后搜索 vbLf 而不是 ANSI LF 字节。

【讨论】:

  • 谢谢.. 与其他人相比,它的工作速度非常快。
  • 嗯,我猜你的UBound() 开始工作了。不客气。
  • 1.6 GB 文件,编号为 11004037。大约 20 秒内的行数
  • 这太快了。太感谢了! @鲍勃77
  • 非常感谢您! ?✨
【解决方案2】:

你可以通过将每一行读入同一个变量来做到这一点。无需保存所有行:

dim s as string
dim n as integer

open "filename.txt" for input as 1

n = 0
do while not eof(1)
  line input #1, s
  n = n + 1
  loop

这个还没有测试过,我已经有一段时间没有做过任何VB6了,但它应该很接近。

【讨论】:

  • 循环到大文件需要更多时间。
  • 确实如此。另一种可能更快的方法是使用 FileSystemObject 将整个文件读入一个字节数组(使用 LOF 查看有多少),然后计算数组中 chr(13) 和/或 chr(10) 的出现次数.
  • +1 FileSystemObject 也会很慢,因为它还会读取整个文件。如果你真的想要速度,你可以使用memory mapped file,但它的工作量很大而且相当先进。
【解决方案3】:

对于 480mb 的二进制文件,1mil+ 0xD (vbcr) 大约需要 6 秒

Dim buff() As Byte
Dim hF As Integer
Dim i As Long, n As Long

hF = FreeFile(0)

Open "c:\windows\Installer\2f91fd.msp" For Binary Access Read As #hF
ReDim buff(LOF(hF) - 1)
Get #hF, , buff()
Close #hF

For i = 0 To UBound(buff)
    If buff(i) = 13 Then n = n + 1
Next

MsgBox n

【讨论】:

  • 感谢回复,但我的VB6不支持Ubound。
  • VB6各个版本都支持UBound,你用的是什么?
  • 我尝试使用 1.6 GB 文件,但在 ReDim buff(LOF(hF) - 1) 上失败(内存不足)
猜你喜欢
  • 1970-01-01
  • 2017-01-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-22
  • 1970-01-01
相关资源
最近更新 更多