2011-04-22 6 views
0

Javaでマルチスレッドを使用してアプリケーションを作成していますが、これを一時停止して再開します。
スレッドはパターンに一致する行を見つけながら、ファイルを1行ずつ読み込みます。私はスレッドを一時停止した場所で続行する必要があります。ファイルを読むために、私はInputStreamReaderとFileInputStreamとの組み合わせでBufferedReaderを使用します。Java:スレッドを一時停止し、ファイル内の位置を取得

fip = new FileInputStream(new File(*file*)); 
fileBuffer = new BufferedReader(new InputStreamReader(fip)); 

ファイル内の位置にファイルポインタが必要なので、このFileInputStreamを使用します。
行を処理するときに、一致する行をMySQLデータベースに書き込みます。スレッド間でMySQL接続を使用するには、ConnectionPoolを使用して、1つのスレッドが1つの接続を使用していることを確認します。

問題は、スレッドを一時停止してから再開するときに、いくつかの一致する行が消えてしまうことです。私はオフセットからバッファサイズを減算しようとしましたが、それでも同じ問題があります。

この問題を解決するうえで、何が間違っているのですか?

いくつかの詳細:

データベースここ

  // Get the connector 
      ConnectionPoolManager cpl = ConnectionPoolManager.getManager(); 
      Connector con = null; 
      while(con == null) 
       con = cpl.getConnectionFromPool(); 
      // Insert the query 
      con.executeUpdate(this.sql.toString()); 
      cpl.returnConnectionToPool(con); 

答えて

1

私は、問題の根本は、あなたがbufferSizeを減算すべきではないということだと思います。むしろ、バッファ内の未読文字の数を減算する必要があります。そして、私はこれを得る方法がないと思う。

私が考えることができる最も簡単な解決策は、読み込まれた文字数を追跡するFilterReaderのカスタムサブクラスを作成することです。そして、次のようにストリームをスタック:

FileReader 
< BufferedReader 
< custom filter reader 
< BufferedReader(sz == 1) 

をあなたがのreadLineを使用できるように、最終的BufferedReaderがあります...しかし、あなたはあなたのフィルターから文字カウントがその位置に一致するように1にバッファサイズを設定する必要がありますアプリケーションが到達しました。

また、カスタムフィルタリーダーで独自のreadLine()メソッドを実装することもできます。

+0

私は以前の記事で言ったように。私はbufferSizeを減算してから、バッファに読み込まれた文字を追加します。この方法では、バッファ内の未読文字の数だけを減算します。これを標準のBufferedReaderで取得する方法はありませんが、標準のBufferedReaderを拡張して、すでに読み込まれている文字の量を取得しました。 – Yoni

+0

@Yoni - おそらく問題は文字数とバイト数です。私はあなたがファイルチャネルにドリルダウンして、その位置が何であるかを調べるべきではないと思います。スタックの上位レベルの文字を数えてください。 –

2

にそれを置くファイル

// Get the position in the file 
public long getFilePosition() throws IOException { 
    long position = fip.getChannel().position() - bufferSize + fileBuffer.getNextChar(); 
    return position; 
} 

で場所を計算するループ

// Regex engine 
    RunAutomaton ra = new RunAutomaton(this.conf.getAuto(), true); 
    lw = new LogWriter(); 

     while((line=fileBuffer.readLine()) != null) { 
      if(line.length()>0) { 
       if(ra.run(line)) { 
         // Write to LogWriter 
         lw.write(line, this.file.getName()); 
         lw.execute(); 
        } 
       } 
      } 
      // Loop when paused. 
      while(pause) { } 
     } 

は、例えば、0です私があなたが探していると信じているもの。あなたは実装の多くを示さなかったので、あなたにギャップを引き起こしているものをデバッグするのは難しいです。 BufferedReaderはそのサイズのバッファを使用しているため、FileInputStreamの位置は8192の倍数になることに注意してください。複数のスレッドを使用して同じファイルを読み取る場合は、this answerが役に立ちます。

public class ReaderThread extends Thread { 
    private final FileInputStream fip; 
    private final BufferedReader fileBuffer; 
    private volatile boolean paused; 

    public ReaderThread(File file) throws FileNotFoundException { 
     fip = new FileInputStream(file); 
     fileBuffer = new BufferedReader(new InputStreamReader(fip)); 
    } 

    public void setPaused(boolean paused) { 
     this.paused = paused; 
    } 

    public long getFilePos() throws IOException { 
     return fip.getChannel().position(); 
    } 

    public void run() { 
     try { 
      String line; 
      while ((line = fileBuffer.readLine()) != null) { 
       // process your line here 
       System.out.println(line); 

       while (paused) { 
        sleep(10); 
       } 
      } 
     } catch (IOException e) { 
      // handle I/O errors 
     } catch (InterruptedException e) { 
      // handle interrupt 
     } 
    } 
} 
+0

私は8192の倍数だと思ったので、私は変数nextCharを読むことができるBufferedReaderの拡張版を作ったので、filepointerから8192を引いてnextCharの値をそれに加えます。この例は私が現在持っているものであり、私にとってはうまくいかない。 – Yoni

0

数日の検索の後、私は実際にバッファサイズを減算し、バッファ内の位置を追加することが正しい方法ではないことを発見しました。ポジションは決して適切ではなく、私はいつもいくつかのラインを欠いていました。
私の仕事をやり遂げる新しい方法を探しているとき、私は多くの文字を数えていないので、文字の数は数えませんでした。しかし、私は別のものを見つけました。ソフトウェアエンジニアMark S.Kolichはa class JumpToLineを作成しました。これはApache IOライブラリを使用して特定の行にジャンプします。また、最後に読んだ行を提供することもできますので、これが本当に必要なものです。
興味のある人のための彼のホームページにいくつかの例があります。

関連する問題