Java 如何在不关闭基础System.in的情况下关闭扫描仪?

Java 如何在不关闭基础System.in的情况下关闭扫描仪?,java,java.util.scanner,nosuchelementexception,system.in,Java,Java.util.scanner,Nosuchelementexception,System.in,如果我关闭一个扫描器对象,创建一个新的扫描器对象,并尝试读取更多的输入,我将得到NoSuchElementException异常 我的代码工作正常,但如果我不关闭扫描仪,它会给我一个警告。但是,如果我关闭它以消除警告,我也会关闭系统。。。我如何避免这种情况 另外,不关闭扫描仪是否有任何后果 编辑:这是我的代码: 这是NameAddressExists()方法: 这些方法是从以下main()方法调用的: 如您所见,我首先调用NameAddressExists()方法,在该方法中,我打开、使用并关闭

如果我关闭一个扫描器对象,创建一个新的扫描器对象,并尝试读取更多的输入,我将得到
NoSuchElementException
异常

我的代码工作正常,但如果我不关闭扫描仪,它会给我一个警告。但是,如果我关闭它以消除警告,我也会关闭
系统。。。我如何避免这种情况

另外,不关闭扫描仪是否有任何后果

编辑:这是我的代码:

这是NameAddressExists()方法:

这些方法是从以下main()方法调用的:

如您所见,我首先调用NameAddressExists()方法,在该方法中,我打开、使用并关闭一个名为“sc”的
扫描仪。这工作得很好,给了我正确的输出。接下来,我调用PanNumberExists()方法,在该方法中,我打开另一个名为“s”的
扫描仪
,并尝试使用它从用户那里获取一些输入。这就是我收到的
NoTouchElementException
异常的地方。如果我在我的NameAddressExists()方法中将
扫描器
'sc'保持打开状态,则不会出现此错误

Scanner scan = new Scanner(new FilterInputStream(System.in) {
    @Override
    public void close() throws IOException {
        // do nothing here ! 
    }
});
或者,通过实现自定义装饰器忽略
close()

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
    }
}
main()中使用时


您可以使用Decorator模式创建无法关闭的自定义
InputStream
,然后将其传递给
扫描仪

import java.io.IOException;
import java.io.InputStream;

public class PreventClosingInputStream extends InputStream {

    private InputStream inputStream;

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

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

    @Override
    public void close() throws IOException {
        // Don't call super.close();
    }

}
然后,在代码中:

PreventClosingInputStream in = new PreventClosingInputStream(System.in);
Scanner s = new Scanner(in);
// ...
s.close(); // This will never close System.in as there is underlying PreventClosingInputStream with empty close() method
使用try-with-resources:

try (PreventClosingInputStream in = new PreventClosingInputStream(System.in);
        Scanner s = new Scanner(in);) {
    // ...
    // resources will be automatically closed except of System.in
}

还有其他问题,查看代码会使问题更容易诊断。这不是正常行为。你能展示你的代码吗?至于不关闭扫描仪——冒着被其他用户射击的风险——如果你的程序不大,那也没什么大不了的。但是,关闭你打开的东西来管理内存是很好的。只要在程序的最后一个块中关闭扫描器,你就成功了。另外,你能提供JDK版本和操作系统吗?可能是
public static void main(String[] args) throws Exception {
        System.setIn(new UnClosableDecorator(System.in));
}
import java.io.IOException;
import java.io.InputStream;

public class PreventClosingInputStream extends InputStream {

    private InputStream inputStream;

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

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

    @Override
    public void close() throws IOException {
        // Don't call super.close();
    }

}
PreventClosingInputStream in = new PreventClosingInputStream(System.in);
Scanner s = new Scanner(in);
// ...
s.close(); // This will never close System.in as there is underlying PreventClosingInputStream with empty close() method
try (PreventClosingInputStream in = new PreventClosingInputStream(System.in);
        Scanner s = new Scanner(in);) {
    // ...
    // resources will be automatically closed except of System.in
}