2016-04-21 2 views
1

Так что у меня это довольно простой код, где я пытаюсь прочитать файл построчно: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 ed at или closed

В каждом примере, который я нахожу, используются выражения Лямбда, я не думаю, что это единственный способ, или это так?

+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

Поток является альтернативой использованию цикла. Вы не можете использовать Stream более одного раза. Даже если вы могли бы использовать поток более одного раза, вызывая 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 На самом деле с Петром объяснение того, как работает Stream, и немного больше исследований/изменений в мыслях, я буду придерживаться подхода Stream, я чувствую, что это идеальный путь. –

Смежные вопросы