2017-04-07 6 views
1

私のアプリケーションでは、別のスレッドがあり、毎分ScheduledExecutorService.scheduleAtFixedRate()で実行され、複数のWebサイトからのRSSフィードを解析します。私はxmlを受け取るためにApache HttpClientを使用しています。BufferedReader.readLine()が時々ハングアップ

サンプルコード:

InputStream inputStream = HTTPClient.get(url);  
String xml = inputStreamToString(inputStream, encoding, websiteName); 

public static String inputStreamToString(InputStream inputStream, String encoding, String websiteName) 
{ 

    BufferedReader bufferedReader = null; 
    PrintWriter printWriter = null; 
    StringBuilder stringBuilder = new StringBuilder(); 

    int letter; 
    try 
    { 
     bufferedReader = new BufferedReader(new InputStreamReader(inputStream, encoding)); 
     printWriter = new PrintWriter(new File("src/doclog/" 
       + websiteName + "_" 
       + new SimpleDateFormat("MM_dd_yyyy_hh_mm_ss").format(new Date(System.currentTimeMillis())) 
       + "_" + encoding + ".txt"), encoding); 
     while((letter = bufferedReader.read()) != -1) 
     { 
      char character = (char) letter; 
      printWriter.print(character);    
      stringBuilder.append(character); 
     } 
    } 
    catch(IOException e) 
    { 
     throw new RuntimeException(e); 
    } 
    finally 
    { 
     try 
     { 
      if(bufferedReader != null) 
      { 
       bufferedReader.close(); 
      } 
      if(printWriter != null) 
      { 
       printWriter.close(); 
      } 
     } 
     catch(IOException e) 
     { 
      e.printStackTrace(); 
     } 
    } 
    System.out.println("String built"); 
    return stringBuilder.toString(); 
} 

とHTTPClientのクラス:タイトルとして

public class HTTPClient 
{ 
    private static final HttpClient CLIENT = HttpClientBuilder.create().build(); 

    public static InputStream get(String url) 
    {  
     try 
     { 
      HttpGet request = new HttpGet(url); 
      HttpResponse response = CLIENT.execute(request); 
      System.out.println("Response Code: " + response.getStatusLine().toString()); 
      return response.getEntity().getContent(); 
     } 
     catch(IOException | IllegalArgumentException e) 
     { 
      throw new RuntimeException(e); 
     } 
    } 
} 

は時々bufferedReader.readLine()は永遠にハングアップする可能性がある、と言います。私はこのトピックについて別の答えを見てきました。bufferedReader.ready()trueを返すかどうかを確認することを提案します。問題は、ウェブサイトがあることです。ウェブサイトはbufferedReader.ready()に常にfalseを返しますが、処理中はうまく解析されます。

私のスレッドがbufferedReader.readLine()でハングしないようにするにはどうすればよいですか?それが重要な場合は

response.getStatusLine().toString()は常にEDIT

HTTP/1.1 200 OK

返す私はちょうどハングアップが発生したときにbufferedReader.ready()trueが実際にあることが分かりました。

EDIT 2

BufferedReader.read()もハング。 1つのウェブサイトを扱うときにハングアップが発生するのは奇妙で、その発生は絶対的にランダムです。アプリケーションは15時間働いていても、問題のない何百もの回答を受け取っていても、起動後10分以内にハングアップすることもできます。私はすべての単一の更新のすべての文字を別々のファイルに書き出し始め、特別なことは何も起こらないことを発見しました。 Xmlの読み取りは、文書の途中で永遠に停止し、最後の文字は<p dir="ltr"&gとなりました。コードを更新しました。

また、私のScheduledExecutorService.scheduleAtFixedRate()実行可能ファイルの最高レベルでThrowableを捕捉してstackTraceを印刷するので、未処理の例外はありません。

答えて

1

ready()メソッドは、読み取り可能な文字があることを示すtrueを返します。問題は、readLine()がブロックされて入力の行末が見つかるまでブロックされることです。

パブリック文字列のreadLine() にIOException

は、テキストの行を読み込みます。行は、改行( '\ n')、改行( '\ r')、またはキャリッジリターン の直後に改行のいずれか1つで終了すると見なされます。

ストリームから読み取る場合、データがライン境界に来るという保証はないので、readLine()コールブロックです。

あなたはブロックしない方法を使用できますが、EOLを自分で確認する必要があります。

公共int型のリード(CHAR [] CBUF、オフINT、INT LEN)にIOException

は、アレイの一部に文字を読み込みます。

このメソッドは、Readerクラスの対応する読み取りメソッド の一般的な規約を実装しています。さらに便利なように、 は、基本となるストリームのread メソッドを繰り返し呼び出すことによって、できるだけ多くの文字を読み取ろうとします。これは読んで反復次のいずれかの条件がtrueになるまで継続 :

The specified number of characters have been read, 
The read method of the underlying stream returns -1, indicating end-of-file, or 
The ready method of the underlying stream returns false, indicating that further input requests would block. 

基本となるストリームのリターンに最初の読み取り-1 ファイルの終わりを示すために、場合、このメソッドは-1を返します。それ以外の場合、このメソッドは実際に読み取られた文字数を 返します。

また、読み込まれた文字から線を再構成する必要があります。一度に行全体を読むのは便利ではありませんが、行なわなければならない方法です。

+0

エンコードに問題はありますか?だから 'readLine()'はEOLを認識できません。 – DaSH

+0

@DaSHそうは思わない。 EOLは標準​​です。 readLineがEOLを認識しなかった場合、それは永遠に読み続けることになり、行変数が大量のメモリを使用し、文字列にゴミで終わるので、大きな問題が発生します。 – whbogado

+0

コードを 'while((letter = bufferedReader.read())!= -1)'に変更しました。ありがたいことに私はラインを分ける必要はありません。 – DaSH

関連する問題