1

unix/linux「tail-f」のJavaIO実装にも同様の問題があります。ただし、このソリューションは、1秒あたり約50〜100行を生成するログファイルには実行できません。

Linuxのテール機能をエミュレートするアルゴリズムがあります。例えば、

File _logFile = new File("/tmp/myFile.txt");
long _filePtr = _logFile.length();

while (true)
{
     long length = _logFile.length();
     if (length < _filePtr)
     {
            // means file was truncated
     }
     else if (length > _filePtr)
     {
            // means something was added to the file
     } 
// we ignore len = _filePtr ... nothing was written to file
}

私の問題は、「ファイルに何かが追加された」場合です(else if()ステートメントを参照)。

else if (length > _filePtr)
{
     RandomAccessFile _raf = new RandomAccessFile(_logFile, "r");
     raf.seek(_filePtr);

     while ((curLine = raf.readLine()) != null)
           myTextPane.append(curLine);

        _filePtr = raf.getFilePointer();
        raf.close();
}

プログラムはwhile((curLine = raf.readLine())....実行時の15秒後にブロックします!(注:プログラムは最初の15秒間正しく実行されることに注意してください)。

このログファイルは非常に高速に書き込まれているため、「無限の猫とマウス」のループに入ると思われるため、raf.readLine()がNULLに達することはないようです。

Linuxのテールをエミュレートする最良の方法は何ですか?

4

3 に答える 3

1

ファイルの長さに基づいてバイトのブロックを取得し、ファイルを解放してByteArrayInputStreamを解析するのが最善だと思います(ファイルから直接読み取ろうとするのではありません)。

したがって、RandomAccessFile#read(byte [])を使用し、返されたファイルの長さを使用してバッファーのサイズを設定します。ファイルの正確な終わりが常に表示されるとは限りませんが、この種のポーリングアルゴリズムではそれが予想されます。

余談ですが、このアルゴリズムはひどいものです-クレイジーなタイトループでIO操作を実行しています-File#length()の呼び出しはブロックされますが、それほど多くはありません。このルーチンがアプリをCPU的にひざまずくようにすることを期待してください。私は必ずしもあなたにとってより良い解決策を持っているわけではありません(まあ、実際には、ソースアプリケーションにファイルではなくストリームに書き込んでもらいますが、それが常に実行可能であるとは限りません)。

上記に加えて、ポーリング遅延を導入することもできます(各ループでスレッドを100msスリープします-GUIに表示しているように見えます-100msの遅延は誰にも害を与えず、パフォーマンスを大幅に向上させますスイング操作の)。

ok-最後の牛肉:EDTで実行されていないコードからSwingコンポーネントを調整しています(私は願っています)。SwingWorker#invokeLater()を使用して、テキストペインを更新します。

于 2010-10-28T04:33:49.973 に答える
0

問題を見つけて解決策を作成したようです。

else ifステートメントの下:

while ((curLine = raf.readLine()) != null)
    myTextPane.append(curLine);

これが問題でした。myTextPane(JTextPaneの派生クラス)のappend(String)メソッドは、不良であるすべての行appendで「setCaretPosition()」を呼び出しました。

つまり、setCaretPosition()は、「スクロールダウン」しようとして50〜100Hzと呼ばれていました。これにより、インターフェイスへのブロッキングオーバーヘッドが発生しました。

簡単な解決策は、StringBufferクラスを作成し、raf.readLine()がnullを読み取るまで「curLine」を追加することでした。

次に、StringBufferと出来上がりを追加します... setCaretPosition()からのブロックはもうありません!

私を正しい方向に導いてくれたKevinに感謝します。

于 2010-10-28T14:52:50.477 に答える
0

テールプログラムはいつでも実行できます。

    BufferedReader in = new BufferedReader(new InputStreamReader(
            Runtime.getRuntime().exec("tail -F /tmp/myFile.txt").getInputStream()));
    String line;
    while ((line = in.readLine()) != null) {
        // process line
    }
于 2010-10-28T17:23:20.107 に答える