在getFileName()方法中创建了对象BufferedReader并将对该对象的引用赋值给变量reader。然后流在最后关闭。
然后调用readStringsFromConsole()方法。这里创建了相同的对象。但是抛出了IOException。为什么会这样?
ps:对不起我的英语:)
异常堆栈:
java.io.IOException: Stream closed
at java.io.BufferedInputStream.getBufIfOpen(BufferedInputStream.java:170)
at java.io.BufferedInputStream.read(BufferedInputStream.java:336)
at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
at java.io.InputStreamReader.read(InputStreamReader.java:184)
at java.io.BufferedReader.fill(BufferedReader.java:161)
at java.io.BufferedReader.readLine(BufferedReader.java:324)
at java.io.BufferedReader.readLine(BufferedReader.java:389)
at com.test.home04.Solution.readStringsFromConsole(Solution.java:55)
代码:import java.io.*;
import java.util.*;
public class Solution
{
public static void main(String[] args)
{
String fileName = getFileName();
ArrayList<String> listStrings = readStringsFromConsole();
writeToFileFromList(fileName, listStrings);
}
public static void writeToFileFromList (String fileName, ArrayList<String> listInputString)
{
PrintWriter writer = null;
try {
writer = new PrintWriter(fileName, "UTF-8");
for (String stringItem : listInputString)
writer.write(stringItem);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (writer != null)
writer.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static ArrayList<String> readStringsFromConsole() {
BufferedReader reader = null;
ArrayList<String> listInputString = new ArrayList<String>();
String line = null;
try {
reader = new BufferedReader(new InputStreamReader(System.in));
while (true)
{
line = reader.readLine();
if ("exit".equals(line))
break;
listInputString.add(line);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (reader != null)
reader.close();
} catch (Exception e) {
e.printStackTrace();
}
return listInputString;
}
}
public static String getFileName()
{
BufferedReader reader = null;
String fileName = null;
try {
reader = new BufferedReader(new InputStreamReader(System.in));
while (fileName == null) {
fileName = reader.readLine();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (reader != null)
reader.close();
} catch (Exception e) {
e.printStackTrace();
}
return fileName;
}
}
}
如果您从System.in
创建阅读器并关闭它,它也会关闭System.in
,即使您创建另一个阅读器也无法再次打开。
总之,不要关闭从System.in
创建的reader。
也正如Andreas在评论中指出的那样,一般准则应该是System.in
在命令行程序的生命周期中只应该包装一次(无论是通过Scanner
, BufferedReader
还是其他东西),并且它永远不应该被关闭。包装应该发生在main()
的开头,包装器对象应该被传递或存储在一个字段中(静态或实例)。
为什么会发生?
它发生是因为你关闭了系统。在你的getFilename
方法。
为什么不在关闭后打开流呢?
基本上,因为你不能,或者如果你问JVM的行为…>> it<& lt;不能。
当close()
被调用时,close被发送给操作系统,操作系统关闭并释放底层文件描述符。一旦关闭,操作系统没有足够的信息来重新打开以前的文件。如果文件描述符用于(未命名的)管道或套接字流,则无法重新建立连接,因为:
-
另一端的应用程序或服务通常已经离开,
-
对于TCP/IP套接字,协议不允许重连
简而言之:如果你以后需要读或写更多的流,不要关闭它,并避免完全关闭System.{in,out,err}
。
现在,如果您的应用程序有文件名或主机/端口,它可以打开一个新的FileReader
或连接一个新的套接字。但是在System.*
流的情况下,该信息对应用程序(或JVM)是不可用的。
但是在您的特定情况下,我怀疑您的意图是getFileName
一次返回一个提供的文件名;即每次调用返回下一个文件名。如果是这种情况,您将不得不以不同的方式实现它:
-
它不应该关闭流或阅读器。
-
不应该打开阅读器(可能)
-
它应该返回它读取的第一行(或下一行),而不是像当前那样读取所有行并返回最后一行。
您正在关闭来自System.in的流。在重用已关闭的流之前需要打开它。如果您从System.in中创建它们,请不要关闭它们。试试这个,
import java.io.*;
import java.util.*;
public class Solution
{
public static void main(String[] args)
{
String fileName = getFileName();
ArrayList<String> listStrings = readStringsFromConsole();
writeToFileFromList(fileName, listStrings);
}
public static void writeToFileFromList (String fileName, ArrayList<String> listInputString)
{
PrintWriter writer = null;
try {
writer = new PrintWriter(fileName, "UTF-8");
for (String stringItem : listInputString)
writer.write(stringItem);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (writer != null)
writer.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static ArrayList<String> readStringsFromConsole() {
BufferedReader reader = null;
ArrayList<String> listInputString = new ArrayList<String>();
String line = null;
try {
reader = new BufferedReader(new InputStreamReader(System.in));
while (true)
{
line = reader.readLine();
if ("exit".equals(line)) {
break;
}
listInputString.add(line);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (reader != null)
//do not close the stream
//reader.close();
} catch (Exception e) {
e.printStackTrace();
}
return listInputString;
}
}
public static String getFileName()
{
BufferedReader reader = null;
String fileName = null;
try {
reader = new BufferedReader(new InputStreamReader(System.in));
while (fileName == null) {
System.out.println("Enter a file name: ");
fileName = reader.readLine();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (reader != null)
//do not close the stream
//reader.close();
} catch (Exception e) {
e.printStackTrace();
}
return fileName;
}
}
}