2016-04-21 87 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方法,但我确实认为这是理想的方式。 –