2013-02-19 16 views
7

Próbuję ponownie uwzględnić dużą i często używaną część mojej aplikacji w osobnych metodach, aby ułatwić jej konserwację.Zamknij Skaner bez zamykania System.in

Niektóre z tych metod prosi użytkownika o wejściu i robi walidacji wejścia, więc użyłem skanera i System.in Ale kiedy zamknę Scanner ja również blisko System.in

Więc moje pytanie brzmi: , czy mogę tylko zapobiec zamknięciu System.in przez ekranowanie go za pomocą metody CloseShieldInputStream, czy też powinienem rozpocząć przekazywanie skanera do metod?

+0

proszę pisać jakiś kod ... – nkukhar

+5

Czy naprawdę trzeba, aby zamknąć skaner? Sugerowałbym, żeby zajął się tym garbage collector - nie można go zamknąć bez zamykania leżącego pod nim przedmiotu. – ddmps

+0

Moja metoda deklaruje skaner, odczytuje i zwraca nextLine(), zamyka skaner i daje mi ból głowy przy następnym uruchomieniu. Jeśli go nie zamknę, Eclipse zaczepia mnie o potencjalny wyciek zasobów, czy można go zignorować? – deepy

Odpowiedz

3

można po prostu zignorować blisko wdrażając własny dekorator.

public class UnClosableDecorator extends InputStream { 

    private final InputStream inputStream; 

    public UnClosableDecorator(InputStream inputStream) { 
     this.inputStream = inputStream; 
    } 

    @Override 
    public int read() throws IOException { 
     return inputStream.read(); 
    } 

    @Override 
    public int read(byte[] b) throws IOException { 
     return inputStream.read(b); 
    } 

    @Override 
    public int read(byte[] b, int off, int len) throws IOException { 
     return inputStream.read(b, off, len); 
    } 

    @Override 
    public long skip(long n) throws IOException { 
     return inputStream.skip(n); 
    } 

    @Override 
    public int available() throws IOException { 
     return inputStream.available(); 
    } 

    @Override 
    public synchronized void mark(int readlimit) { 
     inputStream.mark(readlimit); 
    } 

    @Override 
    public synchronized void reset() throws IOException { 
     inputStream.reset(); 
    } 

    @Override 
    public boolean markSupported() { 
     return inputStream.markSupported(); 
    } 

    @Override 
    public void close() throws IOException { 
     //do nothing 
    } 
} 

i używać go w głównej

public static void main(String[] args) throws Exception { 
     System.setIn(new UnClosableDecorator(System.in)); 
} 
+0

Czy nie byłoby to tak samo jak pisanie własnej wersji CloseShieldInputStream? – deepy

+0

Nie jestem do końca pewien, co masz na myśli, ale jeśli chcesz wykonać pewne akcje ze strumieniem wejściowym przy zamknięciu, to akcje w metodzie UnClosableDecorator.close() – nkukhar

+1

CloseShieldInputStream to strumień proxy, który zapobiega zamknięciu strumienia wejściowego . http://commons.apache.org/io/apidocs/org/apache/commons/io/input/CloseShieldInputStream.html – deepy

1

może po prostu niech będzie bez jego zamykania, wystarczy ustawić zmienną gospodarstwa null

+0

Z tym Eclipse daje ostrzeżenie o tym, że skaner nigdy nie jest zamknięty, czy można go bezpiecznie zignorować? – deepy

+0

Myślę, że jest to udoskonalony styl programowania. Programista może w końcu zostawić otwarte zasoby, które rzeczywiście muszą zostać zamknięte. –

11

Wystarczy użyć niestandardowego FilterInputStream zamiast System.in:

new FilterInputStream(System.in) { 
    @Override 
    public void close() throws IOException { 
     //don't close System.in! 
    } 
} 
+1

sposób prostszy niż zaakceptowana odpowiedź! dzięki. –

+2

To jest właśnie to, co robi komenda '[CloseShieldInputStream] (http://commons.apache.org/proper/commons-io/apidocs/org/apache/commons/io/input/CloseShieldInputStream.html) i jeśli skończysz w tej pozycji możesz chcieć spojrzeć na projekt swojego oprogramowania. Tego typu rozwiązanie nie powinno być potrzebne, chyba że pracujesz z rozwiązaniami innych firm. (dotyczy wszystkich odpowiedzi tutaj) – deepy