Sep 27, 2013

Write to a file in Java - BufferedOutputStream and BufferedWriter

In Java Write operation can be performed using FileOutPutStream and FileWriter. For writing streams of character, FileWriter is preferred and FileOutputStream is used for binary data like images.
FileWriter -  writing streams of characters 
FileOutputStream -  writing streams of raw bytes 

Write into file using FileOutputStream :- 

FileOutputStream is used to write binary data preferably. FileOutputStream extends OutputStream class and when an instance of  FileOutputStream(file,boolean) is created, a file descriptor object is created internally. File descriptor acts as an handle to the underlying machine-specific structure representing an open file. i.e: File descriptor binds stream with the file being used for write operation. Constructor of FileOutputStream takes filename and boolean(optional - indicating streams that bytes will be written to the end of the file or at the beginning). Default value of second parameter is false(stream will add bytes at beginning). However, if true is passed bytes are added at end of file.
Following sample program read and input image (binary input) and write to a new file. Here we have two methods:- writeBinaryStreamSlowestAndSimple and writeBinaryStreamEfficient. First one most in efficient one because input is not buffered, however in second one input stream is buffered and it is more efficient. Always prefer to buffer input/output stream before using it. Sample output below shows why we should prefer to use buffer with stream. Without buffer it write operation took 88 milliseconds and with buffering it just took 5 millisecond.

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Scanner;

public class FileWriteOperationBinaryDataInput {

 private static Scanner scn;

 // Without buffered input:- Read input file and write to output file
 public static void writeBinaryStreamSlowestAndSimple(File outputFile,
   File inputFile) {
  int byteCoint;
  Long starttime = System.currentTimeMillis();
  try {
   FileInputStream is = new FileInputStream(inputFile);
   // Creates a file descriptor
   FileOutputStream os = new FileOutputStream(outputFile);
   while ((byteCoint = is.read()) != -1) {
    os.write(byteCoint);
   }
   is.close();
   os.close();

  } catch (IOException e) {
   e.printStackTrace();
  }
  System.out.println("Total time spent in writing "
    + "without buffered input is (in millisec) "
    + (System.currentTimeMillis() - starttime));

 }

 // With buffered input:- Read input file and write to output file
 public static void writeBinaryStreamEfficient(File outputFile,
   File inputFile) {
  int byteCoint;
  Long starttime = System.currentTimeMillis();
  try {
   FileInputStream is = new FileInputStream(inputFile);
   // Buffered input stream and loop over buffered result
   BufferedInputStream bis = new BufferedInputStream(is);

   FileOutputStream os = new FileOutputStream(outputFile);
   BufferedOutputStream bos = new BufferedOutputStream(os);
   while ((byteCoint = bis.read()) != -1) {
    bos.write(byteCoint);
   }

//Closes this file input/output stream and releases any system resources associated with the stream.
   is.close(); 
   os.close();

  } catch (IOException e) {
   e.printStackTrace();
  }
  System.out.println("Total time spent in writing "
    + "with buffered input is (in millisec) "
    + (System.currentTimeMillis() - starttime));

 }

 public static void main(String[] args) {
  System.out.println("Enter choice 1 or 2: ");
  scn = new Scanner(System.in);
  int choice = scn.nextInt();
  switch (choice) {
  case 1:
   writeBinaryStreamSlowestAndSimple(new File(
     "E:\\devline_logo_new.png"), new File(
     "E:\\devline_logo.png"));
   break;
  case 2:
   writeBinaryStreamEfficient(new File("E:\\devline_logo_new.png"),
     new File("E:\\devline_logo.png"));
   break;
  default:
   break;
  }

 }
}
===========Sample output==================
Enter choice 1 or 2:
1
Total time spent in writing without buffered input is (in millisec) 88

Enter choice 1 or 2:
2
Total time spent in writing with buffered input is (in millisec) 5
===========================================

Write into file using FileWriter :-

FileWriter is most convenient to use for text based write operation, FileWriter extends OutputStreamWriter(a bridge from character streams to byte streams) and FileWriter internally uses write() operaion of OutputStreamWriter.
On each invocation of a write() method in turn invokes encoding converter on the given character(s) and the resulting bytes are accumulated in a byte buffer before being written to the underlying output stream, write() operation is very costly stream is not wrapped in buffer.
In order to avoid frequent converter invocations, it is recommended to wrap Outputstream/FileWriter in BufferedWriter. Below sample program shows the differences of wrapping or not wrapping FileWriter in BufferedWriter.
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Scanner;

public class FileWriteOperationTextDataInput {

 private static BufferedReader br;
 private static FileWriter fw;
 private static FileReader fr;
 private static Scanner scn;

 // Without buffered input:- Read input file and write to output file
 public static void writeTextWithoutBufferedInput(File outputFile,
   File inputFile) {
  int readCount;
  Long starttime = System.currentTimeMillis();
  try {
   fr = new FileReader(inputFile);
   fw = new FileWriter(outputFile);
   while ((readCount = fr.read()) != -1) {
    fw.write(readCount);
   }
   fr.close();
   fw.close();
  } catch (IOException e) {
   e.printStackTrace();
  }

  System.out
    .println("Total time spent in write operation " +
      "without buffered input(in milliseconds)  "
      + (System.currentTimeMillis() - starttime));
 }

 // With buffered input:- Read input text file and write to output file
 public static void writeTextWithBufferedInput(File outputFile,
   File inputFile) {
  int readCount;
  Long starttime = System.currentTimeMillis();
  try {
   FileReader fr = new FileReader(inputFile);
   br = new BufferedReader(fr);
   fw = new FileWriter(outputFile);
   BufferedWriter bwr = new BufferedWriter(fw);
   while ((readCount = br.read()) != -1) {
    bwr.write(readCount);
   }
   br.close();
   fw.close();
  } catch (IOException e) {
   e.printStackTrace();
  }
  System.out
    .println("Total time spent in write operation" +
      " with buffered input(in milliseconds)  "
      + (System.currentTimeMillis() - starttime));
 }

 public static void main(String[] args) {
  System.out.println("Enter choice 1 or 2: ");
  scn = new Scanner(System.in);
  int choice = scn.nextInt();
  switch (choice) {
  case 1:
   writeTextWithoutBufferedInput(new File("E:\\output.xml"), new File(
     "E:\\input.xml"));
   break;
  case 2:
   writeTextWithBufferedInput(new File("E:\\output.xml"), new File(
     "E:\\input.xml"));
   break;
  default:
   break;
  }

 }
}
=========== Sample output=============
Enter choice 1 or 2:
1
Total time spent in write operation without buffered input(in milliseconds)  68
Enter choice 1 or 2: 
2
Total time spent in write operation with buffered input(in milliseconds)  27
===================================

Write operation in append mode :-  

Both class FileWriter and FileOutputStream support writing file in append mode- it means on each call of write method streams(character or byte) are appended at end of file and previous written data persist. Below sample program uses both class and shows how to perform write operation in append mode. On execution of following program(two times one for each case) both content is written to file, as shown in sample output.

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.Scanner;

public class FileWriteOperationAppendMode {
 private static Scanner scn;
 private static BufferedWriter bw;
 private static FileWriter fw;
 static private File outoutFile = new File("E:\\output.txt");

 // write text using FileOutputStream - In append mode
 // bytes will be written to the end of the file rather than the beginning.
 public static void writeTextUsingFileOutputStreamInAppendMode(
   String inputText, File outputFile) {
  try {
   // Creates a file descriptor
   FileOutputStream fos = new FileOutputStream(outputFile, true);
   bw = new BufferedWriter(new OutputStreamWriter(fos));
   bw.append(inputText);
   bw.newLine();
   bw.close();
  } catch (IOException e) {
   e.printStackTrace();
  }

 }

 // write text using FileWriter, In append mode
 // Characters written to the end of the file rather than the beginning.
 public static void writeTextUsingFileWriterInAppendMode(String inputText,
   File outputFile) {
  try {
   fw = new FileWriter(outputFile, true);
   fw.append(inputText);
   fw.close();
  } catch (IOException e) {
   e.printStackTrace();
  }

 }

 public static void main(String[] args) {
  System.out.println("Enter choice 1 or 2: ");
  scn = new Scanner(System.in);
  int choice = scn.nextInt();

  switch (choice) {
  case 1:
   for (int i = 0; i < 5; i++) {
    writeTextUsingFileWriterInAppendMode("inputViaWriter " + i,
      outoutFile);
   }

   break;
  case 2:
   for (int i = 0; i < 5; i++) {
    writeTextUsingFileOutputStreamInAppendMode(
      "inputViaOutputStream " + i, outoutFile);
   }

   break;
  default:
   break;
  }

 }
}
========Sample output==================
Enter choice 1 or 2:
1
Enter choice 1 or 2: 
2
Output.txt content:- 
inputViaWriter 0inputViaWriter 1inputViaWriter 2inputViaWriter 3inputViaWriter 4
inputViaOutputStream 0
inputViaOutputStream 1
inputViaOutputStream 2
inputViaOutputStream 3
inputViaOutputStream 4
=======================================
Location: Hyderabad, Telangana, India