2014-03-27 2 views
0

개발중인 응용 프로그램의 콘솔 입력을 단순화하기 위해 ConsoleInput이라는 클래스에서 작업하고 있습니다. 그것을 테스트하는 동안 BufferedReader를 닫을 수없고 새로운 ConsoleInput 클래스를 인스턴스화 할 수없는 것으로 나타났습니다. BufferedReader를 닫지 않고 얻을 수는 있지만 그럼에도 불구하고 흥미로운 문제입니다. 왜 내가 그것을 닫을 수 없는지, 내가 그것을 바꿀 수있는 일을 배우고 싶습니다.BufferedReader가 제대로 닫히지 않았습니다.

ConsoleInput 클래스 :이 클래스의

package frontend; 

import java.util.Date; 
import java.text.ParseException; 
import java.text.SimpleDateFormat; 
import java.io.*; 

public class ConsoleInput { 
    private BufferedReader buf = null; 
    private boolean ignoreconfirm = false; 
    private boolean confirmation = false; 
    private boolean closed = false; 
    private String dateformat = "yyyy-MM-dd"; 

    private boolean confirm(String value) throws IOException { 
     boolean accept = false; 
     boolean answer = false; 
     String l = "I"; 

     while (!accept) { 
      System.out.print(l + "s '" + value + "' correct (Y/N) ?: "); 
      String line = buf.readLine(); 
      line = line.trim(); 
      line = line.toLowerCase(); 
      if (line.equals("y") || line.equals("yes")) { 
       accept = true; 
       answer = true; 
      } else if (line.equals("n") || line.equals("no")) { 
       accept = true; 
       answer = false; 
      } 
      if (!accept) System.out.print("Try confirmation again, "); 
      l.toLowerCase(); 
     } 

     return answer; 
    } 

    public String getString() throws IOException, ExcConsoleInputClosed { 
     if (closed) throw new ExcConsoleInputClosed(); 
     boolean accept = false; 
     String line = null; 

     while (!accept) { 
      line = buf.readLine(); 
      if (confirmation && !ignoreconfirm) { 
       accept = confirm(line); 
       if (!accept) System.out.print("Try input again: "); 
      } else { 
       accept = true; 
      } 
     } 

     return line; 
    } 

    public Integer getInt() throws IOException, ExcConsoleInputClosed { 
     boolean accept = false; 
     boolean parsed = false; 
     Integer value = null; 
     String input = null; 

     while (!parsed) { 
      if (confirmation) ignoreconfirm = true; 
      input = getString(); 
      if (confirmation) ignoreconfirm = false; 
      input.trim(); 

      if (confirmation) accept = confirm(input); 
      else accept = true; 
      if (!accept) System.out.print("Try input again: "); 
      else { 
       try { 
        value = new Integer(Integer.parseInt(input)); 
        parsed = true; 
       } catch (NumberFormatException e) { 
        System.out.print("Error parsing your input, try again: "); 
       } 
      } 
     } 

     return value; 
    } 

    public Date getDate() 
      throws IOException, ExcConsoleInputClosed { 
     boolean accept = false; 
     boolean parsed = false; 
     Date value = null; 
     String input = null; 
     SimpleDateFormat format = new SimpleDateFormat(dateformat); 

     while (!parsed) { 
      if (confirmation) ignoreconfirm = true; 
      input = getString(); 
      if (confirmation) ignoreconfirm = false; 
      input.trim(); 

      if (input.equals("help")) { 
       System.out.println("Enter a date with format " + dateformat + "."); 
      } else { 
       if (confirmation) accept = confirm(input); 
       else accept = true; 
       if (!accept) System.out.print("Try input again: "); 
       else { 
        try { 
         value = format.parse(input); 
         parsed = true; 
        } catch (ParseException e) { 
         System.out.print("Error parsing your input, try again: Fuck"); 
        } 
       } 
      } 
     } 

     return value; 
    } 

    public void toggleConfirm() { 
     confirmation = !confirmation; 
    } 

    public boolean confirmation() { return confirmation; } 

    public void close() throws IOException { 
     closed = true; 
     buf.close(); 
    } 

    public ConsoleInput() { 
     buf = new BufferedReader(new InputStreamReader(System.in)); 
    } 

} 

단위 테스트 :

public class feConsoleInput { 
    public static void main(String[] args) { 
     ConsoleInput console = new ConsoleInput(); 

     System.out.println("Fetching input from console."); 
     for (int c=0; c <= 1; c++) { 
      try { 
       System.out.print("Enter a string: "); 
       String text = console.getString(); 
       System.out.println("You entered: " + text); 

       System.out.print("Enter a integer: "); 
       Integer number = console.getInt(); 
       System.out.println("You entered: " + number); 

       System.out.println("Enter a date..."); 
       Date date = console.getDate(); 
       System.out.println("You entered: " + date.toString()); 
       console.close(); 
      } catch (IOException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } catch (ExcConsoleInputClosed e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 

      System.out.println(""); 
      console = new ConsoleInput(); 
      console.toggleConfirm(); 
     } 
    } 
} 

그것이 내가 스트림이 IOException이이 폐쇄 얻을 닫은 후 두 번째로 실행됩니다. ConsoleInput 클래스 생성자는 내가 아는 한 새로운 생성자를 생성해야합니다. 당신이 BufferedInputStream을 닫으면

Fetching input from console. 
Enter a string: A string of input. 
You entered: A string of input. 
Enter a integer: 42 
You entered: 42 
Enter a date... 
2012-12-07 
You entered: Fri Dec 07 00:00:00 EST 2012 
java.io.IOException: Stream closed 
Enter a string: 

    at java.io.BufferedInputStream.getBufIfOpen(BufferedInputStream.java:162) 
    at java.io.BufferedInputStream.read(BufferedInputStream.java:325) 
    at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:282) 
    at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:324) 
    at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:176) 
    at java.io.InputStreamReader.read(InputStreamReader.java:184) 
    at java.io.BufferedReader.fill(BufferedReader.java:153) 
    at java.io.BufferedReader.readLine(BufferedReader.java:316) 
    at java.io.BufferedReader.readLine(BufferedReader.java:379) 
    at frontend.ConsoleInput.getString(ConsoleInput.java:45) 
    at test.feConsoleInput.main(feConsoleInput.java:17) 
+0

ConsoleInput 클래스에 console.close()와 같은 콘솔을 닫고 그 메소드에서 close 또는 nullified 메소드를 작성할 수 있습니다. –

+0

콘솔 객체를 닫을 때'System.in'을 닫았습니다. – locoyou

답변

2

, 또한 너무 기본 System.in 스트림을 닫습니다. 이 취소 할 수 없습니다.

일반적인 해결 방법은 외부 판독기를 닫을 때 닫히지 않도록 CloseShieldInputStream으로 System.in을 랩핑하는 것입니다.

public ConsoleInput() { 
    buf = new BufferedReader(new InputStreamReader(
      new CloseShieldInputStream(System.in))); 
} 

또는 전체 프로그램 기간 동안 ConsoleInput 클래스의 인스턴스 하나를 활성 상태로 유지하십시오.

관련 문제