Search code examples
javaiofileoutputstreamprintwriter

PrintWriter not appending content in the right order


I have a list that contains objects (whose constructor contains another inner object). When I'm trying to print the list to a file, I go through each object and call the object's respective writer methods.

public void writer(String file, boolean append) {
    File path = new File("../Opdracht6_2/src/" + file);
    try {
        PrintWriter write = new PrintWriter(new FileOutputStream(path,
                append));
        for (SuperObject o : this.list) {
            if (o instanceof Object1) {
                ((subObject1) w).writer1(file);
            }
            if (o instanceof Object2) {
                ((subObject3) w).writer2(file);
                
            }if (o instanceof Object3) {
                ((subObject3) w).writer3(file);
                
            }
        }
        write.close();
    } catch (FileNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

In the object's writer method I try to first print a line which says what type it is and then call the writer method for the innerobject. After that I want current object's arguments to be printed and than it goes back to the lists writer method

public void writer1(String file) {
    File path = new File("../Opdracht6_2/src/" + file);
    try {
        PrintWriter write = new PrintWriter(
                new FileOutputStream(path, true));
        //below is the string I want to print before the innerobject appends 
        //its own arguments to the file
        write.append("String\r\n");
        this.innerobject.innerwriter();
        write.append(this objects arg);
        write.close();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

The innerobject's writer

public void innerwriter(String file) {
    File path = new File("../Opdracht6_2/src/" + file);
    try {
        PrintWriter write = new PrintWriter(
                new FileOutputStream(path, true));
        write.append(this objects arg);
        write.close();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

Now the thing that is actually happening is that the line that I'm trying to append first gets appended after the innerobject's arguments even though I have put it before the method that calls the innerobject's writer. It looks like this then in the file:

inner objects arg

string

outer objects arg

Can someone explain why?


Solution

  • It's better not to use a Writer in each method here. Use a single StringBuilder to append the content and pass it through the methods. It could be that the Writer is not properly flushing the contents in the order in which content is appended. Specifically, the statement write.close() inside innerwriter would flush the contents of the inner object before the "String\r\n" is actually written by the Writer in the caller method.

    You can avoid creating multiple Writers and use a StringBuilder instead:

    // pass a StringBuilder to append
    public void innerwriter(StringBuilder sb) {
        sb.append(this objects arg);
    }
    

    And when you're done with appending all content, write it using the Writer created only once:

    PrintWriter write = new PrintWriter(new FileOutputStream(path,
                append));
    StringBuilder sb = new StringBuilder();
    for (SuperObject o : this.list) {
        if (o instanceof Object1) {
            ((subObject1) w).writer1(sb);
        }
        if (o instanceof Object2) {
            ((subObject3) w).writer2(sb);
    
        } if (o instanceof Object3) {
            ((subObject3) w).writer3(sb);
    
        }
    }
    
    write.append(sb.toString());
    write.close();