为什么不在关闭后打开流?

时间:2015-10-14 22:08:35

标签: java stream

在方法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;
    }
}
}

3 个答案:

答案 0 :(得分:4)

如果您从System.in创建了一个阅读器并将其关闭,它也会关闭System.in,即使您创建了另一个阅读器,也无法再次打开它。

简而言之 - 不要关闭从System.in创建的读者。

正如安德烈亚斯在评论中指出的那样,一般准则应该是System.in只能在命令行程序的生命周期内被包装一次(无论是Scanner,{{1 ,或其他东西),它永远不应该被关闭。包装应该可能发生在BufferedReader的开头,包装器对象应该传递或存储在字段(静态或实例)中。

答案 1 :(得分:1)

  

为什么会这样?

之所以发生这种情况,是因为您在getFilename方法中关闭了System.in。

  

为什么不在关闭后打开流?

基本上,因为你不能,或者如果你问的是JVM的行为......&gt;&gt;它&lt;&lt;可&#39;吨

当调用close()时,close将被发送到关闭并释放基础文件描述符的操作系统。关闭后,操作系统没有足够的信息来重新打开以前的文件。如果文件描述符用于(未命名的)管道或套接字流,则无法重新建立连接,因为:

  • 另一端的应用程序或服务通常会消失,

  • 对于TCP / IP套接字,协议不允许重新连接。

简而言之:如果您需要稍后从中读取或写入更多内容,请不要关闭流,并避免完全关闭System.{in,out,err}

现在,如果您的应用程序具有文件名或主机/端口,则可以打开新的FileReader或连接新的套接字。但是对于System.*流,该信息不可用于应用程序(或JVM)。

但在您的特定情况下,我怀疑您的意图getFileName一次返回一个提供的文件名;即每次调用都会返回 next 文件名。如果是这种情况,您将不得不以不同的方式实施它:

  • 它不应该关闭流或阅读器。

  • 它不应该打开读者(可能)。

  • 它应该返回它读取的第一行(或下一行)而不是读取所有行并返回最后一行,就像它当前那样。

答案 2 :(得分:0)

您正在从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;
    }
}
}