2016-04-21 3 views
1

でtxtファイルの行を読んだから、私は行毎にファイルを読み込むしようとしているこの非常に単純なコードを持っている:Javaのライン

if(new File(filesDir).listFiles() != null){ 
    for(File file : new File(filesDir).listFiles()){ 
     try { 
      Stream<String> stream = Files.lines(Paths.get(file.getAbsolutePath())); 
      for(int i = 0 ; i < stream.toArray().length; i++){ 
       System.out.println(stream.toArray()[i]); 
      } 
      stream.close(); 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
    } 
} 

をしかし、それはSysoutに到達したとき、それは例外をスロー:

java.lang.IllegalStateException:スレッド「メイン」java.lang.IllegalStateExceptionで

例外ストリームが既にオペレート又は起因する

閉じられた:java.lang.IllegalStateExceptionを:ストリームが既にoperatされていますエドワード・クローズ

ラムダ式が使用されているすべての例は、私はそれが唯一の方法だとは思わないのですか?

+0

'listFiles()'を2回呼び出さないでください。これはディスクを大量に使用する操作です。 – EJP

+1

@EJP入力行ごとにtoArray()を2回呼び出す方法(作業したと仮定して) –

+1

['Files.list'](https://docs.oracle.com/javase/8/docs/api)を使用できます。 /java/nio/file/Files.html#list-java.nio.file.Path-) 'listFiles()'を使用する代わりに。 – Tunaki

答えて

4

ストリームは、ループを使用する代わりに使用できます。ストリームを複数回使用することはできません。ストリームを複数回使用しても、1行の入力に対して2回ずつtoArray()を呼び出すと、非常に高価になります。あなたは何ができるか

try (Stream<String> stream = Files.lines(file.toPath())) { 
    stream.forEach(System.out::println); 
} 

です。注:このアプローチを使用しての重要な利点は、それがそれを読み取って、ファイルを印刷することができるということです。これは、ファイルがどれほど大きくても、それを読み取ることができることを意味します。すべての行にコレクションまたは配列を使用すると、読み込んだファイルのサイズは、メモリの量によって制限されます。

+0

私はストリームを反復したいがforEachを使用しないで、通常のforループでそれを達成できる方法はあるのだろうか? –

+2

通常、ストリームをストリームとして使用します。ループにはリストを使用するだけです(メモリに収まる場合)。 'java.nio.Files.readAllLines(Path)'を使ってそれを実現することができます。それが収まらない場合は、 'Stream.spliterator()'を使ってストリームをイテレータに変換することができ、これから通常の命令的スタイルで反復することができます。 – Dici

+0

@Dici実際にストリームがどのように動作するかについてのPeterの説明と、Streamアプローチに固執すると思ったらもう少し研究/変更して、私はそれが理想的な方法だと感じています。 –