Search code examples
javaprintwriter

PrintWriter erases file of contents before the close() function executed


I am trying to write contents of my parsed HTML with PrintWriter so I can convert HTML to the other formats. But PrintWriter erases file of contents before the close() function executedçI can use other file writing techniques but I am wondering why PrintWriter behave like this.

for (Element element : elements) {
    if (element.tagName() == "a") {                
        PrintWriter writer2 = new PrintWriter("contenthtml.html", "UTF-8");
        writer2.print(a.ExtractHTMLByIDandDomain(Domain + element.attr("href"), Content_HTML_ID));
        Process proc = Runtime.getRuntime().exec("pandoc -f html -t asciidoc contenthtml.html  >> contentasciidoc.adoc");
        //Thread.sleep(5000); //I have tried wait but it didn't work
        writer2.flush();
        writer2.close();
    }

Solution

  • There are a few problems with your code:

    1. You cannot compare strings with '==', as '==' compares references. If element.getTagName() is "a", whether that if on line 2 of your paste actually fires depends on the situation, but it probably wont.

    2. A PrintWriter is a resource. Resources need to be closed; if you do not close them, the resource remains open indefinitely, and this is called a resource leak. Use the Automatic Resource Management construct for a convenient way to do so.

    3. You create the printwriter, tell the printwriter to write some data, you do not flush or close the resource, you then exec another process, and finally after that process completes, you flush/close. Which means, the file is empty, as printwriter buffers. You should write your file and then close your resource, and only then call the external process; both you and the process you launch having the same file open at the same time is confusing and problematic, and in this case, unneccessary, so, don't.

    4. Runtime.getRuntime().exec() is NOT bash and NOT a command line prompt. The concept of redirecting via >> someFile.txt is a bashism/command-promptism. Runtime has no idea what you're talking about and will just pass it along as an argument to the launched process. Invoke bash if you need bash's redirection features or write the redirection in java by reading the outputstream of the process and appending it to the file yourself.

    Applying all 4 fixes:

    create a file named 'run.sh' containing:

    #!/bin/sh
    pandoc -f html -t asciidoc contenthtml.html >> contentasciidoc.asciidoc
    

    and update your java code:

    for (Element element : elements) {
        if ("a".equalsIgnoreCase(element.tagName()) {
            try (PrintWriter writer2 = new PrintWriter("contenthtml.html", "UTF-8")) {
                writer2.print(a.ExtractHTMLByIDandDomain(Domain + element.attr("href"), Content_HTML_ID));
            }
        }
        Process proc = Runtime.getRuntime().exec("/usr/bin/bash run.sh");
    }