2

私の問題でいくつかの代替案を教えていただけないでしょうか。

基本的に、平均 800 万行の .txt ログ ファイルを読んでいます。約600メガの純粋な生のtxtファイル。

私は現在、streamreader を使用して、ログ ファイル内の重要な部分の並べ替えとフィルター処理を行っている 800 万行で 2 つのパスを実行していますが、そのために、私のコンピューターは 1 回の完全な実行に約 50 秒かかります。

これを最適化できる 1 つの方法は、最初のパスを最後に読み取りを開始することです。これは、最も重要なデータが最後の約 200k 行にあるためです。残念ながら、私は検索しましたが、ストリームリーダーはこれを行うことができません. これを行うためのアイデアはありますか?

いくつかの一般的な制限

  • 行数は変動します
  • ファイルのサイズが異なります
  • 重要なデータの場所はさまざまですが、最後の 200k 行で約

アイデアを提供するために、ログ ファイルの最初のパスのループ コードを次に示します。

Do Until sr.EndOfStream = True                                                                              'Read whole File
            Dim streambuff As String = sr.ReadLine                                                      'Array to Store CombatLogNames
            Dim CombatLogNames() As String
            Dim searcher As String

    If streambuff.Contains("CombatLogNames flags:0x1") Then                                             'Keyword to Filter CombatLogNames Packets in the .txt

        Dim check As String = streambuff                                                                'Duplicate of the Line being read
        Dim index1 As Char = check.Substring(check.IndexOf("(") + 1)                                    '
        Dim index2 As Char = check.Substring(check.IndexOf("(") + 2)                                    'Used to bypass the first CombatLogNames packet that contain only 1 entry


        If (check.IndexOf("(") <> -1 And index1 <> "" And index2 <> " ") Then                           'Stricter Filters for CombatLogNames

            Dim endCLN As Integer = 0                                                                   'Signifies the end of CombatLogNames Packet
            Dim x As Integer = 0                                                                        'Counter for array

            While (endCLN = 0 And streambuff <> "---- CNETMsg_Tick")                                    'Loops until the end keyword for CombatLogNames is seen

                streambuff = sr.ReadLine                                                                'Reads a new line to flush out "CombatLogNames flags:0x1" which is unneeded
                If ((streambuff.Contains("---- CNETMsg_Tick") = True) Or (streambuff.Contains("ResponseKeys flags:0x0 ") = True)) Then

                    endCLN = 1                                                                          'Value change to determine end of CombatLogName packet

                Else

                    ReDim Preserve CombatLogNames(x)                                                    'Resizes the array while preserving the values
                    searcher = streambuff.Trim.Remove(streambuff.IndexOf("(") - 5).Remove(0, _
                    streambuff.Trim.Remove(streambuff.IndexOf("(")).IndexOf("'"))                       'Additional filtering to get only valuable data
                    CombatLogNames(x) = search(searcher)
                    x += 1                                                                              '+1 to Array counter

                End If
            End While
        Else
            'MsgBox("Something went wrong, Flame the coder of this program!!")                          'Bug Testing code that is disabled
        End If
    Else
    End If

    If (sr.EndOfStream = True) Then

        ReDim GlobalArr(CombatLogNames.Length - 1)                                                      'Resizing the Global array to prime it for copying data
        Array.Copy(CombatLogNames, GlobalArr, CombatLogNames.Length)                                    'Just copying the array to make it global

    End If
Loop
4

2 に答える 2

1

BaseStreamを目的の読み取り位置に設定できますが、特定のLINEに設定することはできません(行を数えるにはファイル全体を読み取る必要があるため)

    Using sw As New StreamWriter("foo.txt", False, System.Text.Encoding.ASCII)
        For i = 1 To 100
            sw.WriteLine("the quick brown fox jumps ovr the lazy dog")
        Next

    End Using
    Using sr As New StreamReader("foo.txt", System.Text.Encoding.ASCII)
        sr.BaseStream.Seek(-100, SeekOrigin.End)
        Dim garbage = sr.ReadLine ' can not use, because very likely not a COMPLETE line
        While Not sr.EndOfStream
            Dim line = sr.ReadLine
            Console.WriteLine(line)
        End While
    End Using

同じファイルで後で読み取りを試みる場合は、(ベースストリームの)最終位置を保存し、次の読み取りで、行の読み取りを開始する前にその位置に進むことができます。

于 2012-11-29T08:14:31.823 に答える
0

私にとってうまくいったのは、最初の4M行をスキップし(ループ内のすべてを囲む単純なifカウンター> 4M)、フィルタリングを行うバックグラウンドワーカーを追加し、重要な場合は行を配列に追加し、メインスレッドが読み続けている間行。これにより、1 日の終わりに約 3 分の 1 の時間を節約できました。

于 2018-01-14T09:48:29.487 に答える