Wednesday, April 15, 2009

Chaining Properties file

In Java, one way of instantiating a Properties object is with Properties(Properties defaults) constructor. The "defaults" parameter allows property files to be stacked together and it is searched only when a particular property is not found. This feature is quite useful during development and testing when we often have conflicting settings. In such cases, editing a single properties file proves to be error-prone and inefficient. Having more than 1 properties file with only properties that need to be different and chaining them together proves to be more safe and easy. Here is an example:

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Properties;

public class LayeringProperties {

public static final String appPropFile = "Props";
public static final String userPropFile = "UserProperties";

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

try {
//Load application's properties from a file
Properties myProps = new Properties();
myProps.load(new FileInputStream(appPropFile));

//Load the user's properties from a file
Properties userProps = new Properties(myProps);
userProps.load(new FileInputStream(userPropFile));

//List the user properties as key=value pairs
System.out.println("User properties");
userProps.list(System.out);

//List the application's properties
System.out.println("Application properties");
myProps.list(System.out);

} catch (FileNotFoundException fe) {
fe.printStackTrace();
} catch (IOException ie) {
ie.printStackTrace();
}
}
}


Here is the output. Notice how the property value for property "admin.name" is different in the 2 Properties object.
User properties
-- listing properties --
admin.contact=phone email
application.name=My Properties
application.version=1.0
admin.name=akku
Application properties
-- listing properties --
application.name=My Properties
application.version=1.0
admin.name=Kutty

Friday, April 10, 2009

Java support for Google App Engine

On the morning of april 7, 2009, Google announced Java support for App Engine. There is a catch, only a list of core Java classes are supported so there is bound to be a debate about it.

I was very excited to hear this news. Google restricted access to the first 10,000 developers who sign up. I wanted to test drive it so I signed up for an account on 7th evening. I was actually surprised to get my account approved the next day. I thought I was late in signing up but looks like I was not.

I downloaded the AppEngine Java SDK and the Google plugin for Eclipse on my Windows laptop. I am a heavy Eclipse user, so was very happy to see the plugin. I followed the directions for installation and setup. It was pretty straightforward unlike some problems I ran into with the Python App Engine installation and setup on Mac last time. I wanted to do it on my mac but it was indisposed at that time. I went ahead and created a project with a simple servlet as per the instructions, uploaded it to my account and everything worked like a charm.

Google also has a running list of frameworks, lanaguages and libraries which will run on the App Engine. Lot of JVM based languages like Jython, Groovy etc are supported. So now a wider community will embrace Google App Engine.

Friday, April 3, 2009

Tim Bray on what's next in Java Web development

I recently listened to a very interesting podcast on the future of Java Web development by Tim Bray who is the Director of Web Technologies at Sun. Tim Bray talks about cloud computing, concurrency challenges, running dynamic languages like Jython on JVM, REST and other emerging Web technologies.

I think it is a nice podcast and if you are interested in these technologies, you might find the talk interesting too.

Tuesday, March 31, 2009

Using Java I/O API to read and write integers as bytes to a binary file

Java I/O API is very vast. I have shown how to use BufferedInputStream and BufferedOutput stream to read and write integers as bytes to a file.My test case only involves 5 integers but the program is meant for a large number of integers.

BufferedInputStream:
My input stream is binary and not character. So I have used the stream type BufferedInputStream. I have wrapped the plain FieInputStream with the BufferedInputStream so that the input can be buffered. Then I have used the following method int read(byte[] b,int off,int len) to read up to len bytes of data from the stream into an array of bytes, thereby, improving performance.

BufferedOutputStream:
I have used the BufferedOutputStream to write all the bytes at once instead of using the plain FileOutputStream.

Efficient way to read integers from a file of bytes

import java.io.*;

public class ReadFile {

private static final int numOfBytesInInt = 4;

/**
* This method reads bytes from a file and converts them to integers.
* @param name filename
* @param numOfBytes Number of bytes to read
* @return Integer array
*/
public static int[] getIntegersStoredAsBytesFromFile(String name, int numOfBytes) throws IOException {
byte[] b = readBytesFromFile(name,numOfBytes);
return convertBytesToInteger(b);
}

/**
* This method actually reads bytes from a file in one shot(hopefully).
* It is more efficient than reading 1 integer or byte at a time in a file.
* @param name filename
* @param numOfBytes Number of bytes to read
*/
public static byte[] readBytesFromFile(String name, int numOfBytes) throws IOException {
BufferedInputStream bis = null;
byte[] b = new byte[numOfBytes];
try {
bis = new BufferedInputStream(new FileInputStream(name));
bis.read(b);
return b;
} finally {
bis.close();
}
}

/**
* This helper method actually converts each 4 bytes into an integer.
* There is also another way of doing it through bit manipulation.
* @param b The byte array to convert to int
* @return The array of ints
*/
public static int[] convertBytesToInteger(byte[] b) throws IOException{
ByteArrayInputStream bai = new ByteArrayInputStream(b);
DataInputStream dis = new DataInputStream(bai);
int len = b.length;
int[] ints = new int[len/numOfBytesInInt]; //4 bytes = 1 int
for (int i = 0,j = 0; i < len; i += numOfBytesInInt, j++) {
ints[j] = dis.readInt();
}
return ints;
}

}


 

Efficient way to write integers as bytes to a file

import java.io.*;
import java.util.Random;

public class WriteFile {

private static final int numOfBytesInInt = 4;

/**
* This method generates integers using random number
* generator, converts each integer to 4 bytes and
* writes it to a file
* @param name filename
* @param numOfBytes Number of bytes to write
*/
public static void generateIntegersAndStoreInFileAsBytes(
String name, int numOfBytes) throws IOException {
//Generate a byte[] of integers
byte[] b = generateIntegersAsBytes(numOfBytes);
//Write them to the file
writeBytesToFile(name,b);
}

/**
* This helper method actually generates the integers
* using random number generator and converts
* each integer to 4 bytes
* @param numOfBytes Number of bytes to generate
* @return Array of bytes
*/
public static byte[] generateIntegersAsBytes(int numOfBytes) throws IOException {
byte[] b = new byte[numOfBytes];
int randomNumber = 0;
Random r = new Random();
for (int offset = 0; offset < b.length; offset += numOfBytesInInt) {
//Generate random int
randomNumber = r.nextInt();
//Just have it here to show what is written into the file
//is what we are reading later..
System.out.println(randomNumber);
//convert int to bytes
intToByte(randomNumber, b, offset);
}
return b;
}

/**
* This method writes all the bytes to a file in a one shot(hopefully without blocking).
* It is more efficient than writing 1 integer at a time in a file.
* @param name filename
* @param b Array of bytes to write
*/
public static void writeBytesToFile(String name, byte[] b) throws IOException{
BufferedOutputStream bos = null;
try {
bos = new BufferedOutputStream(new FileOutputStream(name));
bos.write(b);
bos.flush();
} finally {
bos.close();
}
}

/**
* This helper method actually converts each integer to 4 bytes.
* See the next method for another way to do the same thing.
* @param integer Integer to be converted to bytes
* @param b The byte array into which the bytes have to be stored
* @param offset The start offset in b
*/
public static void intToByte(int integer, byte[] b, int offset) throws IOException {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(bos);
dos.writeInt(integer);
dos.flush();
System.arraycopy(bos.toByteArray(), 0, b, offset, numOfBytesInInt);
}


/* Instead of using the intToByte method, one could also manually convert
* the integer to an array of bytes using bit arithmetic.
* Here is a way to do it. To use this method, just replace the call
* to the method intToByte() with generateByte() above
*
* private static void generateByte(int integer, byte[] b, int offset) {
b[offset]=(byte)((integer & 0xff000000)>>>24);
b[offset+1]=(byte)((integer & 0x00ff0000)>>>16);
b[offset+2]=(byte)((integer & 0x0000ff00)>>>8);
b[offset+3]=(byte)((integer & 0x000000ff));
}*/

}

 

Test It

import java.io.*;
import static java.lang.System.out;

public class TestingFiles {

private static final String filename = "INPUTBYTES";

/*
* I am just testing with 5 integers but you can practically
* use any number which is a multiple of 4.
*/
private static final int numOfBytes = 20;

public static void main(String[] args) throws IOException{
out.println("Writing to File");
WriteFile.generateIntegersAndStoreInFileAsBytes(filename,numOfBytes);
out.println("Reading from File");
int[] ints = ReadFile.getIntegersStoredAsBytesFromFile(filename,numOfBytes);
for (int i: ints) {
out.println(i);
}
}


}


Here is the output:
Writing to File
931158145
189423544
641759623
-1731070039
1477642147
Reading from File
931158145
189423544
641759623
-1731070039
1477642147