Search code examples
javafilewriter

Write to the same file using BufferWriter from multiple classes


I want to output my result to a file. I use BufferWriter as below:

public class class1{
...
void print()
     {
     System.out.println("The name "+outName()+" Tel: "+outNumber());
       try{
          PrintWriter printWriter=new PrintWriter(new BufferedWriter(new FileWriter("myfile.txt", true)));
          printWriter.println("The name "+outName()+" Tel: "+outNumber());
        }catch (IOException e){}
       }

    }     

However I have another class and main function also having their own print functions

public class class2{
    ...
    void print()
         {
         System.out.println("The name "+outName()+" Tel: "+outNumber());
           try{
              PrintWriter printWriter=new PrintWriter(new BufferedWriter(new FileWriter("myfile.txt", true)));
              printWriter.println("The name "+outName()+" Tel: "+outNumber());
            }catch (IOException e){}
           }

        }  

public static void main(String[] args) throws IOException{

try{
    PrintWriter printWriter=new PrintWriter(new BufferedWriter(new FileWriter("myfile.txt", true)));
    ...
    printWriter.println("something");

printWriter.close();
    }catch(IOException e){ }

}

The code pass the compilation, but only the output from the main function appear in the output file. How to fix it please?


Solution

  • There are three (OK ... make that four, no five) significant problems with your code.

    1. In class2 you don't close or flushthePrintWriter` after you have finished writing. That means that the data will never be written out to the file. That's why you never see the output.

      This is the obvious bug. But the rest of the problems are also important. Arguably MUCH MORE important ... so keep reading.

    2. The print() method in class2 leaks file descriptors (!). Each time you call it, it will open a file descriptor, write stuff ... and drop it on the floor. If you call print() repeatedly, the FileWriter constructor will fail. You need to close the file, and the cleanest way to ensure it always happens is to write the code like this:

      try (PrintWriter printWriter = 
               new PrintWriter(new BufferedWriter(
                   new FileWriter("myfile.txt", true)))) {
          printWriter.println(...);
      }
      

      This is a "try with resource" ... and it guarantees that the resource (printWriter) will be closed when the scope exits.

    3. You are squashing exceptions.

      try {
          PrintWriter printWriter - ...
      } catch (IOException e) {
          // SQUASH!!!
      }
      

      This is really, really bad. Basically, you have written your code to ignore the exception. Pretend it never happened ... and throw away the information in the exception that would say why it happened.

      You should only ever squash an exception if you are absolutely sure that you will only catch expected exceptions, and that ignoring them is absolutely correct. Here, it isn't. If an IOException is thrown here, you need to know why!

    4. Opening multiple streams to write to the same file is a recipe for problems. The streams won't be synchronized, and you are likely to see the output interleaved in the output file in unexpected ways. If the output pipelines include buffering (like yours do), the problem is worse.

    5. You have serious Java style issues:

      • A class name should always start with an uppercase letter. Always. Even in example code snippets ...

      • Code should be consistently indented. I recommend using SP characters rather than TAB characters because tabs don't display consistently.

      • There are style rules about where you should and should not put spaces and line breaks. For example, there should always be whitespace around a binary operator. Find a Java style guide, read it and format your code accordingly.

      Always write your code so that >>other people<< can read it.