21

I normally use PrintWritter object to create and write to a file, but not sure if its the best in terms of speed and security compare to other ways of creating and writing to a file using other approaches i.e.

Writer writer = new BufferedWriter(
             new OutputStreamWriter(
             new FileOutputStream("example.html"), "utf-8"));   
writer.write("Something");

vs

File file = new File("example.html");
BufferedWriter output = new BufferedWriter(new FileWriter(file));          
output.write("Something");

vs

File file = new File("example.html");
FileOutputStream is = new FileOutputStream(file);
OutputStreamWriter osw = new OutputStreamWriter(is);    
Writer w = new BufferedWriter(osw);
w.write("something");

vs

PrintWritter pw = new PrintWriter("example.html", "UTF-8");
pw.write("Something");

Also, when to use one over the other; a use case scenario would be appreciated. I'm not asking for how to create and write to file, I know how to do that. Its more of compare and contrast sort of question I'm asking.

Simple-Solution
  • 4,209
  • 12
  • 47
  • 66
  • You don't have to create any `Writer` - you can simply write into the stream: `BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream('example.file'); bos.write("something".getBytes());` – Aleks G Oct 15 '14 at 10:55
  • 2
    @AleksG - But using *Writers* is different from using *Streams*. They are meant for different reasons. Right? – TheLostMind Oct 15 '14 at 11:02
  • 2
    @TheLostMind Yes, but the OP didn't specify what his ultimate goal is. – Aleks G Oct 15 '14 at 11:02
  • 2
    @AleksG - I guess he wants to know when to use one over another. – TheLostMind Oct 15 '14 at 11:05
  • @AleksG - I've amended the question and added few more lines explaining the my intention. Sorry – Simple-Solution Oct 15 '14 at 11:21
  • 3
    Whatever you do, always specify encoding explicitly. I know it's compelling to just rely on the system encoding ("they're all going to use Windows after all") but it will bite back sooner or later. – biziclop Oct 15 '14 at 11:29

3 Answers3

6

I prefer:

boolean append = true;
boolean autoFlush = true;
String charset = "UTF-8";
String filePath = "C:/foo.txt";

File file = new File(filePath);
if(!file.getParentFile().exists()) file.getParentFile().mkdirs();
FileOutputStream fos = new FileOutputStream(file, append);
OutputStreamWriter osw = new OutputStreamWriter(fos, charset);
BufferedWriter bw = new BufferedWriter(osw);
PrintWriter pw = new PrintWriter(bw, autoFlush);
pw.write("Some File Contents");

which gives you:

  1. Decide whether to append to the text file or overwrite it.
  2. Decide whether to make it auto-flush or not.
  3. Specify the charset.
  4. Make it buffered, which improves the streaming performance.
  5. Convenient methods (such as println() and its overloaded ones).
Eng.Fouad
  • 115,165
  • 71
  • 313
  • 417
  • 3
    I believe you have a typo in `if(!file.exist()) file.mkdirs();` should be `if(!file.exists()) file.mkdirs();`, ie, missing an 's' on the method. Otherwise, thanks for your version. – Rui Carvalho Jan 10 '17 at 16:49
  • 1
    Also, `PrintWritter pw = new PrintWriter(bw, autoFlush);` should be `PrintWriter pw = new PrintWriter(bw, autoFlush);` – Rui Carvalho Jan 10 '17 at 17:05
  • Then there's the missing try / catch clause needed. – Rui Carvalho Jan 10 '17 at 17:31
  • 1
    `if(!file.exists()) file.mkdirs();` is obvious wrong. you will get a directory named 'foo.txt'. At last you will get a `FileNotFoundException...(Is a directory)`. The correct way is `if(!file.exists()) file.getParentFile().mkdirs();` – Loyea Apr 18 '19 at 22:26
2

The best solution, as usual, depends on your task: either you work with text or with binary data. In the first case you should prefer writers, in the second - streams.

You ask for comparison of approaches to write TEXT into files.

The last case in your question is the best one for writing/creation new text files. It is suitable for 99% of practical tasks.

PrintWritter pw = new PrintWriter("example.html", "UTF-8");
pw.write("Something");

It is short and readable. It supports explicit encoding and buffering. It does not require unnecessary wrappers.

Other old-fashion approaches can and should be used in those cases, where this solution is not applicable. E.g. you want to append any text to file. In this case you have no choice except to use writers based on stream wrappers (unfortunately, FileWriter doesn't support explicit encoding).

ursa
  • 4,404
  • 1
  • 24
  • 38
1

Honestly, I don't know if this is the best option, but I think that is a System like, common accepted abstraction:

In.java:

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

public class In {

    public In() {
    }

    /**
     * Tranforms the content of a file (i.e: "origin.txt") in a String
     * 
     * @param fileName: Name of the file to read
     * @return String which represents the content of the file
     */
    public String readFile(String fileName) {

        FileReader fr = null;
        try {
            fr = new FileReader(fileName);
        } catch (FileNotFoundException e1) {
            e1.printStackTrace();
        }

        BufferedReader bf = new BufferedReader(fr);

        String file = "", aux = "";
        try {
            while ((file = bf.readLine()) != null) {
                aux = aux + file + "\n";
            }
            bf.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return aux;
    }
}

Out.java:

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;

public class Out {

    public Out() {}

    /**
     * Writes on the file named as the first parameter the String which gets as second parameter.
     * 
     * @param fileName: Destiny file
     * @param message: String to write on the destiny file
     */
    public void writeStringOnFile(String fileName, String message) {
        FileWriter w = null;
        try {
            w = new FileWriter(fileName);
        } catch (IOException e) {
            e.printStackTrace();
        }
        BufferedWriter bw = new BufferedWriter(w);
        PrintWriter wr = new PrintWriter(bw);

        try {
            wr.write(message);
            wr.close();
            bw.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

IO.java:

public class IO {

    public Out out;
    public In in;

    /**
     * Object which provides an equivalent use to Java 'System' class
     */
    public IO() {
        this.setIn(new In());
        this.setOut(new Out());
    }

    public void setIn(In in) {
        this.in = in;
    }

    public In getIn() {
        return this.in;
    }

    public void setOut(Out out) {
        this.out = out;
    }

    public Out getOut() {
        return this.out;
    }
}

Therefore, you can use the class IO almost in the same way you will use System.

Hope it helps.

Clemencio Morales Lucas.