2015-06-16 8 views
7

Od the docs:Czy zamknięcie strumienia zamyka źródło BufferedReader?

Strumienie mają metodę BaseStream.close() i wdrożyć AutoCloseable, ale prawie wszystkie przypadki strumień rzeczywistości nie muszą być zamknięte po użyciu. Zasadniczo, tylko strumienie, których źródłem jest kanał IO (takie jak , jak te zwrócone przez Files.lines (Path, Charset)) będą wymagały zamknięcia. Większość strumieni jest obsługiwana przez kolekcje, tablice lub generujące funkcje , które nie wymagają specjalnego zarządzania zasobami. (Jeśli strumień wymaga zamknięcia, nie może być uznana jako zasób w try-with-zasobów oświadczeniu.)

Kiedy tworzę Stream<String> stosując metodę lines() na BufferedReader jak widać poniżej, nie zamknięcie Stream również zamknąć BufferedReader?

try (Stream<String> lines = new BufferedReader(new InputStreamReader(process.getInputStream())).lines()) { 
    // Do stuff 
} 

// Is the BufferedReader, InputStreamReader and InputStream closed? 

Niektóre naprawdę szybkie testy próbowałem powiedzieć nie (pole z BufferedReaderin nie jest null), ale jestem zdezorientowany przez następnym zdaniu, ponieważ to przykładem jest I/O jak dobrze, dobrze?

Ogólnie, tylko strumienie, których źródłem jest kanał IO (takiego jak te zwrócony przez Files.lines (Ścieżka Charset)) wymaga zamknięcia.

Jeśli nie, muszę zamknąć zarówno instancji, albo zamykając BufferedReader wystarczą?


Idealnie, chciałbym zwrócić Stream<String> z jakiejś metody, bez konieczności martwić klienta o czytelników. W tej chwili stworzyłem dekorator Stream, który również zamyka czytnik, ale jest to łatwiejsze, jeśli nie jest to konieczne.

+0

Gdzie można sprawdzić, że ' BufferedReader' jest zamknięty? Wewnątrz bloku 'try'? –

+0

Przetestowałem go po jawnym wywołaniu 'close' w' Stream' i sprawdzeniu pola za pomocą debuggera. Próba automatycznego doboru jest przykładem tego, jak chciałbym go użyć. – nhaarman

+0

Zobacz też: http://stackoverflow.com/questions/34072035/why-is-files-lines-and-similar-streams-not-automatically-closed/34073306#34073306 –

Odpowiedz

2

Nie, wygląda na to, że tak nie jest. Ponieważ strumień jest tworzony przy użyciu

return StreamSupport.stream(Spliterators.spliteratorUnknownSize(
      iter, Spliterator.ORDERED | Spliterator.NONNULL), false); 

który nie przechodzi żadnego odniesienia do tej BufferedReader

+1

Brak połączenia z 'statycznym strumieniem publicznym linie (Path path, Charset cs) 'w pytaniu. Wywoływane jest ['Reader.lines()'] (https://docs.oracle.com/javase/8/docs/api/java/io/BufferedReader.html#lines--). –

+0

Dobrze, poprawiłem moją odpowiedź ... – JiriS

+0

To wydaje się być przekonującym argumentem, dlaczego 'BufferedReader' nie zostałby zamknięty z' Stream'. Patrząc na źródło 'linii', nie widzę powodu, dla którego' Stream' musi być zamknięty, i wnioskuję, że tylko 'BufferedReader' powinien zostać zamknięty. – nhaarman

2

W swoim pytaniu nie pokazują, jak utworzyć Reader który jest argument new BufferedReader(in). Ale z moich własnych testów nie ma powodu, aby zakładać, że Stream zamyka ten argument.

wykonując następujące czynności należy zamknąć każdy:

import java.io.BufferedReader; 
import java.io.File; 
import java.io.FileInputStream; 
import java.io.InputStreamReader; 
import java.io.Reader; 
import java.util.stream.Stream; 

public class SOPlayground { 

    public static void main(String[] args) throws Exception { 
     try (Reader in = new InputStreamReader(new FileInputStream(new File("/tmp/foo.html"))); 
       BufferedReader reader = new BufferedReader(in); 
       Stream<String> lines = reader.lines()) { 
      lines.forEach(System.out::println); 
     }   
    } 
} 
+0

Dzięki, znalazłem to również. Dodałem dodatkowe informacje do pytania. – nhaarman

+1

Używanie 'try (Stream lines = Files.lines (Paths.get ("/tmp/foo.html "))) {...}' byłoby znacznie prostsze. –

1

Jeśli chcesz odroczyć zamknięcie czytnika do dostarczonego Stream trzeba powołać Stream.onClose():

static Stream<String> toStream(BufferedReader br){ 
    return Stream<String> lines = br.lines() 
     .onClose(asUncheckedAutoCloseable(br)); 
} 

static Runnable asUncheckedAutoCloseable(AutoCloseable ac) { 
    return() -> { 
    try { 
     ac.close(); 
    } catch (Exception e) { 
     throw new RuntimeException(e); 
    } 
    } 
}