2

I have to create a mini-interpreter in Java for a "Toy Language" and in this project, I have to include a FileTable which is a class having as private field a HashMap<Integer, FileData>, where FileData is:

public class FileData {
    private String fileName;
    private BufferedReader fileDescriptor;

    // methods...
}

Also, I have another class OpenRFile which has a method execute(String fileName). This method creates a BufferedReader object for the given fileName and a FileData object which is added in the FileTable.

public class OpenRFile implements Statement {
    private String varName;
    private String fileName;

    // methods...
    public OpenRFile(String v, String f) {
        this.varName = v;
        this.fileName = f;
    }

    @Override
    public PrgState execute(PrgState p) {
        IDictionary<Integer, FileData> fileTable = p.getFileTable();
        IDictionary<String, Integer> symTable = p.getSymTable();

        if (symTable.contains(this.varName))
            throw new InterpreterException("Var name already exists.");

        for (Integer i: fileTable.getAll()) {
            if (fileTable.get(i).getFileName().equals(this.fileName))
                throw new InterpreterException("File is already open.");
        }

        try (BufferedReader br = new BufferedReader(new FileReader(this.fileName))) {
            Integer id = IDGenerator.generateID();
            symTable.add(this.varName, id);
            fileTable.add(id, new FileData(this.fileName, br));
        }
        catch (IOException e) {
            throw new InterpreterException(e.getMessage());
        }

        return p;
    }

    @Override
    public String toString() {
        return "OpenRFile(" + this.varName + ", " + this.fileName + ");";
    }
}

Later, in another class: ReadFile, the method execute just retrieves the FileData object from the FileTable and calls the method readLine() on the BufferedReader object, and this is the moment when I get the Steam closed error.

public class ReadFile implements Statement {
    private Expression exp;
    private String varName;

    // methods...
    public ReadFile(Expression e, String v) {
        this.exp = e;
        this.varName = v;
    }

    @Override
    public PrgState execute(PrgState p) {
        IDictionary<String, Integer> symTable = p.getSymTable();
        IDictionary<Integer, FileData> fileTable = p.getFileTable();

        Integer id = this.exp.eval(symTable);

        if (!fileTable.contains(id))
            throw new InterpreterException("File not found.");

        Integer read;

        try  {
            BufferedReader br = fileTable.get(id).getFileDescriptor();
            //BufferedReader br = new BufferedReader(new FileReader(fileTable.get(id).getFileName()));
            String line = br.readLine();
            if (line == null)
                read = 0;
            else
                read = Integer.parseInt(line);
        }
        catch (IOException e) {
            throw new InterpreterException(e.getMessage());
        }

        if (symTable.contains(this.varName))
            symTable.update(this.varName, read);
        else
            symTable.add(this.varName, read);

        return p;
    }

    @Override
    public String toString() {
        return "ReadFile(" + this.exp + ")";
    }
}

If I retrieve the fileName from the FileData object and create a new BufferedReader object, it works. But if I try to call readLine() directly on the object I already have, I get the error.

8
  • 1
    You're trying to read from a stream which you've closed elsewhere. Without relevant code, we cannot help you further. Commented Nov 11, 2017 at 20:51
  • I don't call the close() method on the BufferedReader object. That's why I can't understand what's the problem. Commented Nov 11, 2017 at 20:52
  • Welcome to Stackoverflow, please read How To Ask. Pay special attention to How To Create MCVE. The more effort you'll put into posting a good question: one which is easy to read, understand and which is on topic - the chances are higher that it will attract the relevant people and you'll get help even faster. Good luck! Commented Nov 11, 2017 at 20:53
  • Add relevant code, BufferedReader can be closed automatically in many cases. Also you can add breakpoint to BufferedReader#close to debug what piece of code closed it. Commented Nov 11, 2017 at 20:53
  • 2
    The try-with-resources block in execute will close the reader. You should store the path to the file, not the open stream. Commented Nov 11, 2017 at 21:02

1 Answer 1

2

You have created BufferedReader and FileReader in try-with-resources block. This means, that close() method was called on both directly after try block, as if there were finally{fileReader.close();bufferedReader.close()}.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.