2016-04-20 9 views
2

この問題は私には面倒です。私はループの中から呼び出されるメソッドを書いた。最初は完全に動作し、その後はちょうどハングアップします。 Java System.in hasNextメソッドは初めて呼び出されたときにのみ動作します

この

はメソッドである:それは情報を取得するのにかかるよう

public static String promptUser(){ 
    String path = ""; 
    Scanner reader = new Scanner(System.in); 

    while (!path.contains(ROOT_FOLDER)){ 
     System.out.println(String.format("Please paste in the directory path from WinSCP, including %s: ", ROOT_FOLDER)); 

     while (true) { 
      if (reader.hasNext()){ 
       path = reader.nextLine(); 
       break; 
      } 
     } 
    } 
    reader.close(); 
    return path; 
} 

そして、これがループ

 while (true) { 
     try { 
      listFiles(promptUser()); 
      break; 
     } 
     catch (Exception e) { 
      e.printStackTrace(); 
      System.err.println(e.getMessage()); 
     } 
    } 

私はそれを初めて実行され、それが何回ユーザーにプロンプ​​トが表示されます必要(ディレクトリパス)。その後、FTPサーバーにその要求を送信し、そのパスが存在しない場合は、引き続きユーザーにプロンプ​​トを表示します。それだけでハングアップラウンドしかし、私のデバッガは、第二の外出先で私に言っている:

 if (reader.hasNext()){ 

キーを入力して打つのいかなる量は、それが継続して得ません。 promptUserの最初の呼び出しで、私はルートフォルダなしで何かを入力することができました。そして、それはルートフォルダを取得するまで尋ね続けます。それでなぜ2回目の呼び出しでそれをしないのですか?

何が起こっているのですか?

答えて

2

あなたはそれが次んpromptUser呼び出し初めて:

  1. System.inをラップScannerを作成します。
  2. 読み込むデータがあるまでブロックするhashNextを呼び出します。
  3. 1行を読みます。
  4. Scannerを閉じます。
  5. 行を返します。あなたがScannerを閉じると

問題が、またあなた近いSystem.inステップ4です。あなたはpromptUser

  1. 呼び出す

    次回はSystem.inをラップ別Scannerを作成します。 System.inはこの時点で閉じています。

  2. Scannerで囲まれたストリームが閉じているため、すぐにfalse ...を返すように、hashNext()を呼び出します。
  3. リピート2.広告怠慢。無限ループがあります。

解決策:ラップするSystem.inまたはScannerを閉じないでください。 System.inをラップする2番目のScannerを作成しないでください。代わりに元のScannerを再利用してください。


しかし、いくつかの点でスキャナをクローズすることが必要なのか?

あなたがラップScanner(オリジナル)System.inストリームをクローズする必要はありません。我々はストリームを閉じる理由は以下のとおりです。

  • は、バッファされたデータは、(出力ストリームのために)書かさせるように、そして
  • は、ファイルディスクリプタのリークを避けるために。

ファイル記述子が漏れているという問題は、プロセス(つまり、JVM)が一度に特定の数のファイルしか開くことができないことです。ファイル記述子がリークした場合、ファイルを開こうとすると予期しないエラーが発生することがあります(IOException)。

System.inの場合、書き込むべきデータはありません。 System.inを開くことはできません(何が接続されているかわからないため)。多くても1つのファイル記述子が「漏洩」する可能性がありますので、問題はありません。

Eclipseは私がすべきことを警告します。

スキャナを閉じるなどのEclipseヒューリスティックスはかなり単純です。この場合、警告は(おそらく)ですが、確かめるにはコードを確認する必要があります。

+0

ありがとうございます、これは私の問題を解決し、あなたは問題を私が主題で見つけた他の質問よりもずっとよく説明しました。しかし、ある時点でスキャナを閉じる必要がありますか? Eclipseは私がすべきことを警告します。 – clickcell

1

次の要素をフェッチするときは、ループ内でbreakを使用しないでください。これにより、while(true)ループが終了します。つまり、最初のアイテムを取得して終了します。

あなたはこのような何かにそれを変更する必要があります。

while(reader.hasNext()) { 
    path = reader.nextLine(); 
    // do something with the path here... 
} 
+0

これは私が試した最初のものですが、それは私に別の問題をもたらします。もう一度最初の呼び出しで正しく動作しますが、2回目の呼び出しでは、入力を待たずにメッセージをコンソールに繰り返し出力し続けます。これが2つのループにまとめられている理由ですが、while(true)ループが存在するかどうかは関係ありません。なぜなら、正しい入力を待つ別のループの内部にあるからです。同じ方法が2つの異なる振る舞いをしているように見えるのは、私は本当に理解できません。 – clickcell

-1

hasNext()

のドキュメントを読んで、このスキャナは、その入力に別のトークンを持っている場合はtrueを返します。このメソッドは、入力をスキャンするのを待つ間にブロックされることがあります。スキャナは入力を超えて進まない。 戻り値: このスキャナに別のトークンがある場合はtrue

したがって、hasNext()は値の入力を待っています。ユーザーが入力した1つの文字列が見つかるまで待機します。

+0

私はpromptUserを初めて呼びますが、2回目には、1日中、Returnキーを押しても何も起こりません。 – clickcell

関連する問題