Friday 3 November 2017

Implement a stream that writes to multiple streams

Implement a OutputStream such that, when you write some information to this stream, it will write to multiple streams.

One of my friend got this interview question, I feel interviewer asked this question to check how comfortable he is while handling streams. The question is abstract, but interviewer seems to be expecting whether the implementation is handling all the cases or not.

Let’s break the question into small tokens.

When you write some information to the stream it should write to multiple streams.
From this statement, it is clear that the stream that we are going to implement should handle multiple output streams.
public class MultiOutputStream extends OutputStream {

 private List<OutputStream> outStreams;

 public MultiOutputStream(OutputStream... outputStreams) {

  if (outputStreams == null) {
   throw new IllegalArgumentException("outputStreams should not be null");
  }

  outStreams = new ArrayList<>();

  for (OutputStream outStream : outputStreams) {
   if (outStream != null) {
    outStreams.add(outStream);
   }
  }
 }

 .....
 .....
 .....
}

Override write methods
Since OutputStream writes information to the streams, we need to override write methods such that, whenever you call write method on this stream, it should call the write operation on all underlying streams.
 @Override
 public void write(int b) throws IOException {
  for (OutputStream outputStream : outStreams) {
   outputStream.write(b);
  }
 }

What about flush and close operations?
Implementation is similar like how we implemented write method in previous step. Whenever user calls flush, we need to flush all the underlying streams and whenever close() is called on this stream, it should close all the underlying streams.
 @Override
 public void flush() throws IOException {
  for (OutputStream outputStream : outStreams) {
   outputStream.flush();
  }
 }

 @Override
 public void close() throws IOException {
  for (OutputStream outputStream : outStreams) {
   outputStream.close();
  }
 }


Find the below working application.

MultiOutputStream.java
package com.sample.streams;

import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;

/**
 * Output stream class to write to multiple streams.
 * 
 *
 */
public class MultiOutputStream extends OutputStream {

 private List<OutputStream> outStreams;

 public MultiOutputStream(OutputStream... outputStreams) {

  if (outputStreams == null) {
   throw new IllegalArgumentException("outputStreams should not be null");
  }

  outStreams = new ArrayList<>();

  for (OutputStream outStream : outputStreams) {
   if (outStream != null) {
    outStreams.add(outStream);
   }
  }
 }

 @Override
 public void write(int b) throws IOException {
  for (OutputStream outputStream : outStreams) {
   outputStream.write(b);
  }
 }

 @Override

 public void write(byte b[]) throws IOException {
  for (OutputStream outputStream : outStreams) {
   outputStream.write(b);
  }
 }

 @Override
 public void write(byte b[], int off, int len) throws IOException {
  for (OutputStream outputStream : outStreams) {
   outputStream.write(b, off, len);
  }
 }

 @Override
 public void flush() throws IOException {
  for (OutputStream outputStream : outStreams) {
   outputStream.flush();
  }
 }

 @Override
 public void close() throws IOException {
  for (OutputStream outputStream : outStreams) {
   outputStream.close();
  }
 }
}

Test.java
package com.sample.streams;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;

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

  PrintStream fileStream1 = new PrintStream(new FileOutputStream("outputFile1.log", true));
  PrintStream fileStream2 = new PrintStream(new FileOutputStream("outputFile2.log", true));

  try (MultiOutputStream multiOutputStream = new MultiOutputStream(fileStream1, fileStream2, System.out)) {
   multiOutputStream.write(new String("Hello World").getBytes());
  }

 }
}



No comments:

Post a Comment