2016-04-21 107 views
1

所以我在那裏我試圖讀取文件裏逐行這個相當簡單的代碼:爪哇 - 逐行讀取一個txt文件行

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編輯或關閉

我找到的每個示例都使用Lambda表達式,我不認爲這是唯一的方法,還是它?

+0

不要調用'listFiles()'兩次。這是一個磁盤密集型操作。 – EJP

+1

@EJP如何調用toArray()每行輸入兩次(假設工作:) –

+1

您可以使用['Files.list'](https://docs.oracle.com/javase/8/docs/api /java/nio/file/Files.html#list-java.nio.file.Path-)而不是使用'listFiles()'。 – Tunaki

回答

4

流是使用循環的替代方法。您不能多次使用流。即使您可以多次使用一個數據流,每次輸入的行號會調用toArray()兩次,都會非常昂貴。

你可以做的是

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

注:使用這​​種方法的顯著優點是它可以打印文件,因爲它讀取它。這意味着無論文件有多大,它仍然可以讀取它。如果每行都使用一個集合或一個數組,則讀取的文件大小將受到您擁有的內存量的限制。

+0

我想迭代流,但不使用forEach,有沒有一種方法,我可以用普通的循環來實現這一點? –

+2

那麼通常你使用流作爲流,如果你想要一個循環只使用一個列表(如果它適合內存)。你可以使用'java.nio.Files.readAllLines(Path)'來存檔它。如果它不合適,你可以使用'Stream.spliterator()'將一個流轉換爲一個迭代器,並且由此可以按照常規的命令式樣迭代。 – Dici

+0

@Dici實際上,Peter對Stream的工作方式進行了解釋,還有一點更深入的研究/思考變化,我會堅持Stream方法,但我確實認爲這是理想的方式。 –