Google

Aug 12, 2013

BeanIO tutorial

BeanIO is an open source Java framework for marshaling and marshaling Java beans from a flat file, stream, or simple String object. It is very powerful with support for XML, CSV, delimited and fixed length stream formats, Object binding, filed validation, integration with spring-batch, etc. Here is a basic tutorial to get started.

Step 1: The sample CSV file to convert to an object of type Person. The first record is a header record, and the subsequent ones are detail records. The file is person.csv under src/main/resources/data

H, 2013-03-12
John,Smith, FAMILY
Peter,Smith, FAMILY
Gregory,Smith, FAMILY


Step 2: Define the dependency jar in pom.xml file.

<!-- beanio -->
<dependency>
 <groupId>org.beanio</groupId>
 <artifactId>beanio</artifactId>
 <version>2.0.2</version>
</dependency>

Step 3:The main class that wires up everything.

package com.mycompany.app10;

import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.beanio.BeanReader;
import org.beanio.StreamFactory;

public class BeanIoMain
{
    
    public void readCSVFileUsingBeanIo()
    {
        StreamFactory factory = StreamFactory.newInstance();
        factory.loadResource("person.xml");
        
        //read it from the classpath : src/main/resources
        InputStream in = this.getClass().getResourceAsStream("/data/persons.csv");
        BeanReader reader = factory.createReader("persons", new InputStreamReader(in));
        Object record = null;
        List<Person> persons = new ArrayList<Person>();
        
        // read records from "input.csv"
        while ((record = reader.read()) != null)
        {
            if ("header".equals(reader.getRecordName()))
            {
                
                @SuppressWarnings("unchecked")
                Map<String, Object> header = (Map<String, Object>) record;
                System.out.println(header.get("fileDate"));
            }
            else if ("detail".equals(reader.getRecordName()))
            {
                Person person = (Person) record;
                persons.add(person);
            }
        }
        
        System.out.println(persons);
    }
    
    public static void main(String[] args)
    {
        new BeanIoMain().readCSVFileUsingBeanIo();
    }
}

Step 3: The POJO Person class.

package com.mycompany.app10;

public class Person
{
    
    private String firstName;
    private String surname;
    private PersonType type;
    
    public String getFirstName()
    {
        return firstName;
    }
    
    public void setFirstName(String firstName)
    {
        this.firstName = firstName;
    }
    
    public String getSurname()
    {
        return surname;
    }
    
    public void setSurname(String surname)
    {
        this.surname = surname;
    }
    
    public PersonType getType()
    {
        return type;
    }
    
    public void setType(PersonType type)
    {
        this.type = type;
    }
    
    @Override
    public String toString()
    {
        return "Person [firstName=" + firstName + ", surname=" + surname + ", type=" + type + "]";
    }
    
}



Step 4: The person.xml under src/main/resources where you can map to your POJO Person.java.

<beanio xmlns="http://www.beanio.org/2012/03">
 <stream name="persons" format="csv">
  <parser>
   <property name="delimiter" value="," />
   <property name="lineSeparator" value="\n" />
   <property name="whitespaceAllowed" value="true" />
  </parser>
   <typeHandler name="personTypeHandler" class="com.mycompany.app10.PersonTypeHandler"/>
  <record name="header" class="map" maxOccurs="1">
   <!-- 'rid' indicates this field is used to identify the record -->
   <field name="recordType" rid="true" literal="H" />
   <!-- 'format' can be used to provide Date and Number formats -->
   <field name="fileDate" type="date" format="yyyy-MM-dd" />
  </record>
  <record name="detail" minOccurs="0" maxOccurs="unbounded"
   class="com.mycompany.app10.Person">
   <field name="firstName" />
   <field name="surname" />
   <field name="type" typeHandler="personTypeHandler" type="com.mycompany.app10.PersonType" />
  </record>
 </stream>
</beanio>

Step 5: Next, the handler class that parses Enums to String.

package com.mycompany.app10;

import org.beanio.types.TypeConversionException;
import org.beanio.types.TypeHandler;

public class PersonTypeHandler implements TypeHandler
{
    
    public Object parse(String text) throws TypeConversionException
    {
        PersonType personType = PersonType.valueOf(text.trim());
        return personType;
    }
    
    public String format(Object value)
    {
        return value != null ? ((PersonType) value).name() : PersonType.SINGLE.name();
    }
    
    public Class<?> getType()
    {
        return PersonType.class;
    }
}

Step 6: The output of the BeanIoMain is:

Tue Mar 12 00:00:00 EST 2013
[Person [firstName=John, surname=Smith, type=FAMILY], Person [firstName=Peter, surname=Smith, type=FAMILY], Person [firstName=Gregory, surname=Smith, type=FAMILY]]



Labels:

Jun 7, 2013

Java OpenCSV tutorial to work with CSV files



BeanIO is an open source Java framework for marshaling and marshaling Java beans from a flat file, stream, or simple String object. It is very powerful with support for XML, CSV, delimited and fixed length stream formats, Object binding, filed validation, integration with spring-batch, etc. But there are scenarios where you need to simply read or write CSV data, OpenCSV framework is quite useful. Here are simple step by step guide to convert Java objects to CSV data.


Step 1: Define in the maven pom.xml file to bring in the OpenCSV jar file.

 <properties>
      <opencsv.version>2.3</opencsv.version>
 </properties>
 
 <dependencies>
    <!-- Open CSV -->
    <dependency>
    <groupId>net.sf.opencsv</groupId>
    <artifactId>opencsv</artifactId>
    <version>${opencsv.version}</version>
    </dependency>
 <dependencies>
 

Step 2: Write the Person model class.

package com.mycompany.app2;

public class Person
{
    private String firstName;
    private String surname;
    private int age;
    
    public String getFirstName()
    {
        return firstName;
    }
    
    public void setFirstName(String firstName)
    {
        this.firstName = firstName;
    }
    
    public String getSurname()
    {
        return surname;
    }
    
    public void setSurname(String surname)
    {
        this.surname = surname;
    }
    
    public int getAge()
    {
        return age;
    }
    
    public void setAge(int age)
    {
        this.age = age;
    }
    
}



Step 3: Write the interface.

package com.mycompany.app2;

import java.util.List;

public interface SimpleWriter
{
    abstract String writeCSV(List persons);
}



Step 4: Write the implementation using the above interface.

package com.mycompany.app2;

import au.com.bytecode.opencsv.CSVWriter;

import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class SimpleWriterImpl implements SimpleWriter
{
    
    private static final char DELIMITER = ',';
    
    public String writeCSV(List<Person> persons)
    {
        StringWriter writer = new StringWriter();
        CSVWriter csvWriter = null;
        
        try
        {
            csvWriter = new CSVWriter(writer, DELIMITER, CSVWriter.DEFAULT_QUOTE_CHARACTER,
                    CSVWriter.NO_ESCAPE_CHARACTER, "\n");
            
            List<String[]> records = new ArrayList<String[]>(10);
            
            for (Person person : persons)
            {
                List<String> record = Arrays.asList(String.valueOf(person.getFirstName()),
                        String.valueOf(person.getSurname()),
                        String.valueOf(person.getAge()));
                
                String[] recordArray = new String[record.size()];
                record.toArray(recordArray);
                records.add(recordArray);
            }
            
            csvWriter.writeAll(records);
            
        }
        
        catch (Exception e)
        {
            e.printStackTrace();
        }
        
        return writer.toString();
    }
    
}



If you want to write to a file, you can use a FileWriter instead of the StringWriter.

Step 5: Write a test class to test it.In practice, a unit test class must be written.

package com.mycompany.app2;

import java.util.ArrayList;
import java.util.List;

public class SimpleWriterTest
{
    public static void main(String[] args)
    {
        Person p1 = new Person();
        p1.setFirstName("John");
        p1.setSurname("Smith");
        p1.setAge(12);
        List persons = new ArrayList(5);
        persons.add(p1);
        
        SimpleWriter sw = new SimpleWriterImpl();
        String csvOutPut = sw.writeCSV(persons);
        System.out.println(csvOutPut);
        
    }
}

Step 6: The output is

"John","Smith","12"

Labels: ,

May 24, 2013

Java new I/O Interview Questions and Answers



The Java New IO is very powerful and it is all about performance!, performance!!, and performance!!!. But, you need to get your head around how the buffers work. Here are some questions and answers that will help you do that. Q. How does the Java NIO (i.e New IO) introduced in Java version 1.4 differ from the old IO?
A. The NIO is all about better performance.

IO NIO (New IO)
Stream oriented. This means that you read one or more bytes at a time, from a stream. What you do with the read bytes is up to you. They are not cached anywhere. Furthermore, you cannot move forward and back in the data in a stream. If you need to move forward and back in the data read from a stream, you will need to buffer yourself first.

Buffer oriented. This means better performance. Data is read into a buffer from which it be processed later. You can move forward and back in the buffer. This gives you a bit more flexibility during processing. However, you also need to check if the buffer contains all the data you need in order to fully process it.
Blocking IO. This means when a thread invokes a read() or write(), that thread is blocked until there is some data to read, or the data is fully written. The thread can do nothing else in the meantime.

Non blocking IO. This means better performance. NIO's non-blocking mode enables a thread to request reading data from a channel, and only get what is currently available, or do nothing at all, if no data is currently available. Rather than remain blocked until data becomes available for reading, the thread can proceed with doing something else.
You need to create additional threads to read and write data in parallel. More threads means more CPU context switching and consuming more thread stacks. Selectors.  This also means better performance. NIO's selectors allow a single thread to monitor multiple channels of input. You can register multiple channels with a selector, then use a single thread to "select" the channels that have input available for processing, or select the channels that are ready for writing. This selector mechanism makes it easy for a single thread to manage multiple channels. This is also known as multiplexing. The Apache MINA package is based on Java NIO to write high performance networking applications. For example, a TCP server.

Here is the diagrammatic overview:



Q. How do you manipulate the buffer in NIO?
A. The NIO buffer  has following 3 state variables -- position, limit, and capacity

  • position: The position value keeps track of how much you have gotten from the buffer. It specifies from which array element the next byte will come. Thus, if you've written 1 bytes as shown below with shaded area to a channel from a buffer, that buffer's position will be set to 1 (starting from 0), referring to the second element of the array as shown in the diagram.
  • limit: The limit variable specifies how much room there is left to put data into -- in the case of reading from a channel into a buffer or how much data there is left to get -- in the case of writing from a buffer into a channel. The position is always less than, or equal to, the limit. The limit is 3 (counting from 0) in the diagram below.
  • capacity:  The capacity of a buffer specifies the maximum amount of data that can be stored in the underlying array. The limit can never be larger than the capacity. The capacity is 6 (counting from 0) in the diagram below.

In the above diagram, the position starts with 0, and after reading 1 byte, it becomes 1 byte, and the limit value of 3 states that there are 2 more bytes to be read. 



Q. What do you understand by terms flip( ) and clear( ) in NIO?
A.

Flip

When you are ready to write your data to an output channel. You must call the flip() method. This method does two key things:

1. It sets the limit to the current position.
2. It sets the position to 0.

You are now ready to begin writing data to a channel from the buffer starting from 0 to the limit.


Clear

After you have done your writes, the final step is to call the buffer's clear() method. This method resets the buffer in preparation for receiving more bytes. Clear does two key things:

1. It sets the limit to match the capacity.
2. It sets the position to 0.


Also, the get and put methods are used to get and put data to and from the buffer respectively. some coding examples are discussed in Java I/O interview Questions and Answers.


Q. What is in the NIO.2 package introduced in Java 7?
A. The more New I/O APIs for the Java Platform (NIO.2) in Java 7 enhance the New I/O APIs (NIO) introduced in Java 1.4 by adding

  • The four asynchronous channels to the java.nio.channels package. 
  •  The java.io.File class is upgraded to the java.nio.file.Path that allows logical manipulating of paths in memory without accessing the file system.
  • The NIO.2 associates the notion of metadata like is hidden, is it a directory, size, access control, etc with attributes and provides access to them through the java.nio.file.attribute package. Since different file systems have different notions about which attributes should be tracked, NIO.2 groups the attributes into views, each of which maps to a particular file system implementation.
  • The NIO.2 provides support for both hard links and symbolic links and the Path class knows how to detect a link and will behave in the default manner if no configuration of behavior is specified.
  • The NIO.2 comes with a set of brand new methods for managing files and directories, such as create, read, write, move, delete, and so on. The most of these tasks are found in the java.nio.file.Files class.
  • The FileVisitor interface introduced in Java 7 makes recursing through directories and files a breeze.
  • The Watch Service API was introduced in Java 7 (NIO.2) as a thread-safe service that is capable of watching  a directory for changes to its content through actions such as create, delete, and modify. This means, with NIO.2, you no longer need to poll the file system for changes or use other in-house solutions to monitor the file system changes.
  • Java 7 (NIO.2) introduces a new interface for working with Random Access Files with its SeekableByteChannel and an interface named NetworkChannel that provides network channel classes for tetworking.

Labels:

May 21, 2013

Java I/O -- the Decorator and proxy design pattern interview questions and answers



Q. Can you explain the decorator design pattern?
A. By implementing the decorator pattern you construct a wrapper around an object by extending its behavior. The wrapper will do its job before or after and delegate the call to the wrapped instance. The decoration happens at run-time. In Java, the wrapper classes like Integer, Double, etc are typical example of a decorator pattern. Another good example is the Java I/O classes as shown below. Each reader or writer will decorate the other to extend or modify the behavior.

String inputText = "Some text to read";
ByteArrayInputStream bais = new ByteArrayInputStream(inputText.getBytes());
Reader isr = new InputStreamReader(bais);
BufferedReader br = new BufferedReader(isr);
br.readLine(); 


As you can see, each reader extends the behavior at run-time. This is the power of object composition as opposed to inheritance. By composing a fewer classes at run-time, desired behavior can be created. Here is another example demonstrating an interleaved reading using a class from the Apache library.

import java.io.*;
import org.apache.commons.io.input.TeeInputStream;

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

        // Create the source input stream.
        InputStream is = new FileInputStream("c:\temp\persons.txt");

        // Create a piped input stream for one of the readers.
        PipedInputStream in = new PipedInputStream();

        // Create a tee-splitter for the other reader. This is from the Apache library
        TeeInputStream tee = new TeeInputStream(is, new PipedOutputStream(in));

        // Create the two buffered readers.
        BufferedReader br1 = new BufferedReader(new InputStreamReader(tee));
        BufferedReader br2 = new BufferedReader(new InputStreamReader(in));

        // You can now do interleaved reads
        System.out.println("1 line from br1");
        System.out.println(br1.readLine());


        System.out.println("2 lines from br2:");
        System.out.println(br2.readLine());
        System.out.println(br2.readLine());
        System.out.println();

        System.out.println("1 line again from br1:");
        System.out.println(br1.readLine());
        System.out.println();
  
   }
}


Q. Can you write a class using the decorator design pattern to print numbers from 1-10, and then decorators that optionally print only even or odd numbers?
A. Java decorator pattern


Q. How does a decorator design pattern differ from a proxy design pattern?
A. In Proxy pattern, you have a proxy and a real subject. The relationship between a proxy and the real subject is typically set at compile time, whereas decorators can be recursively constructed at run time. The Decorator Pattern is also known as the Wrapper pattern. The Proxy Pattern is also known as the Surrogate pattern. The purpose of decorator pattern is to add additional responsibilities to an object. These responsibilities can of course be added through inheritance, but composition provides better flexibility as explained above via the Java I/O classes. The purpose of the proxy pattern is to add an intermediate between the client and the target object. This intermediate shares the same interface as the target object. Here are some scenarios in which a proxy pattern can be applied.

  • A remote proxy provides a local representative for an object in a different address space.Providing interface for remote resources such as web service or REST resources or EJB using RMI.
  • A virtual proxy creates expensive object on demand.
  • A protection proxy controls access to the original object.Protection proxies are useful when objects should have different access rights.
  • A smart reference is a replacement for a bare pointer that performs additional actions when an object is accessed.
  • Adding a thread-safe feature to an existing class without changing the existing class's code. This is useful when you do not have the freedom to fix thread-safety issues in a third-party library.
The proxy design pattern is explained with a dynamic proxy class to gather performance results in the blog entitled  Java Interview Questions and Answers - performance testing your Java application.



Q. Can you list some of the best practices relating to Java I/O
A.
  1. As demonstrated in Java I/O interview Questions, it is a good practice to close all instances of java.io.Closeable in a finally block.
  2. Use BufferedReader and BufferedWriter to increase efficiency because IO performance depends a lot from the buffering strategy. 
  3. Favor NIO over old IO because the old I/O is stream oriented and uses a blocking IO, whereas the NIO (aka New IO) is Buffer oriented, uses Non blocking I/O and has selectors. 
  4. To avoid issues like "the file reading works in Windows but not in Unix", use java.io.File constructors instead of working with file names as String. The FilenameUtils class in Apache. commons IO handles issues relating to operating systems. 
  5. Apache FileUtils class is  very handy for touching, copying, moving, deleting, calculating the checksum, calculating last modified date, listing and filtering directories, comparing file content, etc.


Other design patterns - real life examples

Labels: ,

May 16, 2013

Java I/O Interview Questions and Answers

Java I/O interview questions are popular with some interviewers, especially the job you are applying for requires file processing. The Java NIO (stands for New I/O) package was introduced in Java version 4 and NIO2 was released in Java version 7.

Q. Why do you need to favor NIO (i.e. New I/O) to old I/O?
A.  A stream-oriented I/O (or old I/O) deals with data one byte at a time. An input stream produces one byte of data, and an output stream consumes one byte of data. It is very easy to create filters and chain several filters together so that each one does its part in what amounts to a single, sophisticated
processing mechanism. On the flip side, stream-oriented I/O is often rather slow.

A block-oriented I/O system deals with data in blocks. The New I/O consumes a block of data in one step. Processing data by the block can be much faster than processing it by byte (i.e. streamed). But block-oriented I/O lacks some of the elegance and simplicity of stream-oriented I/O.


The examples below read the content of this file and print it to a console. In reality, you can do whatever you want once you have read it like mapping to Java POJOs, etc.

Q. Can you describe different ways in which you can read data from a file?
A. Files can be read a number of ways. Here is a sample file named person.csv in a folder c:\temp\tlm.

FirstName, Surname, Age
John,Smith, 35
Peter,John, 28
Shirley,John,34


1. The I/O way using a BufferedReader


package com.arul;

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

/**
 * This is a slower way using the old io
 */
public class ReadFileOldIOWay
{ 
    public static void main(String[] args) throws IOException
    {
        BufferedReader br = null;
        String sCurrentLine = null;
        try
        {
            br = new BufferedReader(
                    new FileReader("c:/temp/tlm/person.csv"));
            while ((sCurrentLine = br.readLine()) != null)
            {
                System.out.println(sCurrentLine); // for demo only. use log.info(...) instead
            }
        }
        catch (IOException e)
        {
            e.printStackTrace(); // quick & dirty for demo only
        }
        finally
        {
            if (br != null)
            {
                br.close();
            }       
        }
    }
}



2. The nio way using a ByteBuffer for smaller files

package com.arul;

import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

/**
 * This is using the nio ByteBuffer for smaller files
 */
public class ReadFileWithByteBuffer
{
    public static void main(String args[]) throws IOException
    {
        RandomAccessFile aFile = null;
        try
        {
            aFile = new RandomAccessFile(
                    "c:/temp/tlm/person.csv", "r");
            FileChannel inChannel = aFile.getChannel();
            long fileSize = inChannel.size();
            ByteBuffer buffer = ByteBuffer.allocate((int) fileSize);
            inChannel.read(buffer);//read the first header line
            buffer.flip();//The limit is set to the current position
            while (buffer.hasRemaining())
            {
                System.out.print((char) buffer.get()); // for demo only. use log.info(...) instead 
            }
            
            inChannel.close();
            
        }
        catch (IOException exc)
        {
            exc.printStackTrace(); //quick & dirty for demo only
            System.exit(1);
        }
        finally
        {
            aFile.close();
        }
    }
}



3. The nio way using a ByteBuffer with chunking for larger files


package com.arul;

import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

/**
 * This is using the nio ByteBuffer chunking for larger files
 */
public class ReadFileWithByteBufferInChunksForLargerFiles
{
    public static void main(String args[]) throws IOException
    {
        RandomAccessFile aFile = null;
        try
        {
            aFile = new RandomAccessFile(
                    "c:/temp/tlm/person.csv", "r");
            FileChannel inChannel = aFile.getChannel();
            ByteBuffer buffer = ByteBuffer.allocate(18);
            while (inChannel.read(buffer) > 0)
            {
                
                buffer.flip();
                while (buffer.hasRemaining())
                {
                    System.out.print((char) buffer.get()); // for demo only. use log.info(...) instead
                }
                buffer.clear();
            }
            
            inChannel.close();
            
        }
        catch (IOException exc)
        {
            exc.printStackTrace(); //quick & dirty for demo only
            System.exit(1);
        }
        finally
        {
            aFile.close();
        }
    }
}


4. The nio way using a MappedByteBuffer for better performance, but beware of the file size

package com.arul;

import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;

/**
 * This is a faster way using the nio MappedByteBuffer
 */

public class ReadFileWithMappedByteBufferWay
{
    public static void main(String[] args) throws IOException
    {
        RandomAccessFile aFile = null;
        
        try
        {
            aFile = new RandomAccessFile
                    ("c:/temp/tlm/person.csv", "r");
            FileChannel inChannel = aFile.getChannel();
            MappedByteBuffer buffer = inChannel.map(FileChannel.MapMode.READ_ONLY, 0, inChannel.size());
            buffer.load();
            for (int i = 0; i < buffer.limit(); i++)
            {
                System.out.print((char) buffer.get()); // for demo only. use log.info(...) instead
            }
            buffer.clear(); // do something with the data and clear/compact it.
            inChannel.close();
        }
        finally
        {
            aFile.close();
        }
    }
}


The output for all the above alternatives is

FirstName, Surname, Age
John,Smith, 35
Peter,John, 28
Shirley,John,34


The nio package is very efficient as it uses buffering and non blocking I/O with selectors compared to the old I/O.

Labels: ,