Jun 7, 2015

Java I/O - ByteArrayInputStream and ByteArrayOutputStream

In previous post we discusses about Java I/O classes classification & class hierarchy and its interdependency. Java support Input and Output(I/O) operations with characters/text and binary stream. FileInputStream,FileReader,FileOutputStream and FileWriter are responsible for supporting character and byte read/write operation in File. In continuation of previous post, here we are discussing about Java I/O classes dedicated for bytes array - ByteArrayInputStream, ByteArrayOutputStream. 

ByteArrayInputStream and ByteArrayOutputStream 

Classes ByteArrayInputStream(BIS) and ByteArrayOutputStream(BOS) provide I/O with an array of bytes. BIS extends InputStream and BOS extends OutputStream. Lets first see the internals of BIS followed by BOS and sample example for the same.
ByteArrayInputStream(BIS) internally maintains a buffer(byte buf[]) and store array of bytes that is provided by BIS constructor. Along with this buffer it also maintains two integer (pos and count) , pos kwwp track of index of the next character to read from the input stream buffer and count is one greater than the position of the last byte within buf. If any moment pos == count, it means end of file has reached.The constructors of BIS are
//BIS buf is initialized with byte buffer passed as argument, pos is set 
//to 0 and count is length of  bye bugger.
public ByteArrayInputStream(byte buf[]) {
 this.buf = buf;
 this.pos = 0;
 this.count = buf.length;
    }
//BIS buf is initialized with byte buffer passed, pos is offset and count is minimum 
//of length of  bye bugger or (offset + length). 
public ByteArrayInputStream(byte buf[], int offset, int length) {
 this.buf = buf;
 this.pos = offset;
 this.count = Math.min(offset + length, buf.length);
 this.mark = offset;
}

Lets write sample code illustrating how do we use BIS and create a generic InputStream handling method dealing with FileInputStream and BIS both.
package com.devinline.javaio;

import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;

public class ByteArrayInputStreamExample {

 public static void main(String[] args) {
  byte[] byteArray = { 97, 98, 99, 78, 71, 100 };
  // pass byteArray input to InputStream handler
  InputStream is = new ByteArrayInputStream(byteArray);
  System.out.println("ByteStreamArray output");
  handleInputStream(is);
  is.close();
  // pass File input to InputStream handler
  InputStream is2;
  try {
   is2 = new FileInputStream("email.properties");
   System.out.println("\nFileInputStream output");
   handleInputStream(is2); is2.close();
  } catch (FileNotFoundException e) {
   e.printStackTrace();
  }
 }
 
 //generic method handling both FileInputStream and ByteInputStream
 private static void handleInputStream(InputStream is) {
  BufferedInputStream bis = new BufferedInputStream(is);
  // read each byte
  int readCount = 0;
  try {
   while ((readCount = bis.read()) != -1) {
    System.out.println((char)readCount);
   }
  } catch (IOException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }

 }

}
======Sample Output=====
ByteStreamArray output
a
b
c
N
G
d

FileInputStream output
I
D
=
N
I
K
==========================
ByteArrayOutputStream(BOS) internally maintains a buffer(byte buf[]) in which data is written. The default size of this byte buffer 32 and it automatically grows as data is written to it. Initial size of buffer is assigned 32 by constructor if no arg is passed.The constructor definition is :
public ByteArrayOutputStream(int size) {
 //byte buffer of length = size argument is created 
  buf = new byte[size];
}
public ByteArrayOutputStream() {
 //default size 32 byte buffer is created 
}
Below is sample program illustrating how BOS is used to write bytes into byte buffer from stream.
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.ByteArrayOutputStream;

public class ByteArrayOutputStreamExample {
 public static void main(String[] args) throws IOException {
  // BOS created of default size 32, no arg passed
  OutputStream os = new ByteArrayOutputStream();
  InputStream is = new FileInputStream(new File("email.properties"));
  BufferedInputStream bis = new BufferedInputStream(is);
  int readCount = 0;
  // Write is into ByteOutputStream
  while ((readCount = bis.read()) != -1) {
   os.write(readCount);
  }
  os.close();
  bis.close();
  
  // Now verify data present in ByteOutputStream using
  // toString()/toArray() method
  System.out.println("ByteOutputStream buffer data is " + os.toString());
 }
}
=======Sample output===========
ByteArrayOutputStream buffer data is : ID = NIK
=============================
Note:- 
  1. Closing a ByteArrayInputStream and ByteArrayOutputStream has no effect. The methods of respective classes can be called after the stream has been closed without  throwing an IOException. For example:- In above sample code, after closing OutputStream(os.close()), we calls os.toString() and display data present in byte buffer.
  2. ByteArrayOutputStream has writeTo(OutputStream out) - which writes the complete contents of this byte array output stream to the specified output stream and toByteArray() - creates a newly allocated byte array of same size. 

Location: Hyderabad, Telangana, India