web-dev-qa-db-ja.com

複数のテキストファイルの行数をすばやく数える方法は?

100を超えるテキストファイルがあり、それぞれの行数を数える必要があります。 Column Aは、E1で指定されたフォルダーにあるファイル名をリストします。いくつかのファイルには100万行を超える行があり、スクリプトの実行に非常に長い時間がかかります。

screenshot

Sub counter()
    Dim fso As New FileSystemObject
    Dim ts As TextStream
    Dim longtext As String
    Dim lines As Variant
    Dim GoToNum As Integer
    Dim Start As Integer
    GoToNum = 2
    Start = 3

    Do Until IsEmpty(Cells(Start, 1))
        GoToNum = GoToNum + 1
        Start = Start + 1
    Loop

    For i = 3 To GoToNum
        If Cells(i, 2).Value <= Cells(2, 5).Value Then
            ConOrg = Cells(1, 4).Value & "\" & Cells(i, 1).Value

            Set ts = fso.OpenTextFile(ConOrg, ForReading, False)
            longtext = ts.ReadAll

            ts.Close
            lines = Split(longtext, vbLf)
            Cells(i, 3) = UBound(lines) - LBound(lines) - 1

        End If
    Next i
End Sub

行ごとにカウントされないように、最後の行の番号(をテキストファイルから)を取得するにはどうすればよいですか?

6
Black Cornail

VBAを使用してテキストファイル内の行をカウントする方法:

40 MBファイル(170万行)
-CountLF = 25.2秒
-CountLines = 2.1秒

14 Bファイル(6行)x 10,000回
-CountLF = 1.3秒
-CountLines = 18.9秒


小さなファイルに適しています:

Function countLF(fName As String) As Long
    Dim st As String
    Open fName For Input As #1: st = Input(LOF(1), 1): Close #1
    countLF = Len(st) - Len(Replace(st, vbLf, "")) + 1
End Function

使用例:

Debug.Print countLF("c:\test.txt")

大きなファイルに適しています:

Function countLines(fName As String) As Long
    countLines = CreateObject("Scripting.FileSystemObject").OpenTextFile(fName, 8, True).Line
End Function

使用例:

Debug.Print countLines("c:\test.txt")

その他のベンチマーク:(2500個の小さなテキストファイル)
Binary Access/Get(4.32s)Kill = 1.17s。 。 。バイナリアクセス用にFを開く#1:ReDimとして読み取る...#1 , bytesを取得する
Line Input/LineInput(4.44s)Kill = 1.11s。 。 。入力としてFを開く#iFile ... Line Input#1、st
Early Bind/ReuseObj(5.25s)Del = 1.12s。 。 。 Set o = New Scripting.FileSystemObject ':st = o.OpenTextFile(F).ReadAll()
Early Bind/FreshObj(11.98s)Del = 1.35s。 。 。 Set o = New Scripting.FileSystemObject ':st = o.OpenTextFile(F).ReadAll()
LateBind/ReuseObj(6.25s)Del = 1.47s。 。 。 Set o = CreateObject( "Scripting.FileSystemObject")
LateBind/FreshObj(13.59s)Del = 2.29s。 。 。 CreateObject( "Scripting.FileSystemObject")を使用

7
ashleedawg

この関数を試してみてください。 FileSystemObjectを使用します。ファイル全体を読み取って1行に分割するよりも高速である必要があります。からインスピレーションを受けた Hey、Scripting guy

Function countLines(fName As String) As Long

    Const ForReading = 1
    Dim objFSO  As Object, objTextFile As Object
    Set objFSO = CreateObject("Scripting.FileSystemObject")
    Set objTextFile = objFSO.OpenTextFile(fName, ForReading)
    objTextFile.ReadAll
    countLines = objTextFile.Line
End Function
1
FunThomas

別のアプローチは、Power Query(Get&Transform Data)を使用することです。

let
    Source = Folder.Files("C:\Users\me\MyFolder"),
    #"Filtered Rows" = Table.SelectRows(Source, each [Extension] = ".txt"),
    #"Added Row Count" = Table.AddColumn(#"Filtered Rows", "Rows In File", each Table.RowCount(Table.FromColumns({Lines.FromBinary([Content])})), Int64.Type),
    #"Removed Columns" = Table.SelectColumns(#"Added Row Count",{"Name", "Rows In File"})
in
    #"Removed Columns"

これはかなり高速に動作します。

1
Olly