Archive for Java

How to read unicode text data using NIO from a SocketChannel

Please note data.compact(); at the bottom of the method readUTF8(). This will save you from loosing available bytes that were not decoded in previous iteration. I hope the following example code to read large text data using NIO will help beginners to NIO.

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CoderResult;
import java.nio.charset.CodingErrorAction;

public class NIOTextReader {
    public static String readUTF8(SocketChannel sc) 
                throws IOException {
        StringBuffer textRead = new StringBuffer();
        final Charset utf8 = Charset.forName("UTF-8");
        CharsetDecoder decoder = utf8.newDecoder();
        decoder.reset();
        decoder.onMalformedInput(CodingErrorAction.REPLACE);
        decoder.onUnmappableCharacter(CodingErrorAction.REPLACE);

        final ByteBuffer data = ByteBuffer.allocate(1024);
        final CharBuffer chBuffer = CharBuffer.allocate(1024);

        while (true) {
            // read the data into the char buffer
            int r = sc.read(data);

            // check for end of data
            if (r == -1) {
                break;
            }

            // prepares the data for decoding/read
            data.flip();

            CoderResult result = null;
            do {
                // Decode byte data into Character data
                result = decoder.decode(data, chBuffer, false);
                chBuffer.flip();
                textRead.append(chBuffer);
                chBuffer.clear();
                if (result.isUnderflow()) {
                    break;
                }
            } while (result.isOverflow());

            // moves the remaining bytes to the beginning that were
            // not decoded
            data.compact();
        }

        return textRead.toString();
    }
}
Advertisements

Leave a Comment

Bengali Typing Tutor

“Bengali Typing Tutor” is an application developed for you if you would like to learn/practice typing in Bengali. This “bangla typing tutor” will help you learn typing in bengali fast. It supports multiple popular Bengali keyboard layouts of different bengali typing softwares available. You can choose the one of your choice. To do that, just right click anywhere on the application window and click ‘Select keyboard layout’. This is the initial release of my application and I hope to add more features in the near future. It is developed using “Java SE”. So you will need Java 1.6+ to run this application.

Features:
1. Supports “Unijoy”,“Somewherein Phonetic” and “Avro Phonetic” keyboard layout.
2. Allows you to choose different lessons.

Screenshot of Bengali Typing Tutor

Installation:
You can easily download Java from http://www.java.com/getjava/ if it is not installed already in your pc. Once you have Java installed in your machine just click http://weaverspark.com/java/typingtutor/download.php to install my “bangla typing practice” application.

Enjoy bangla typing…

Note: I started the development of this application long days back when I started learning Java. I could not continue the development of this application after I joined my job. But few days back I decided to work on it again and here is the output.

Comments (21)

Java Synchronization Review

All java programmers are familiar with java synchronization. But how much do you really know about it? Are you sure that you have solid knowledge on this concept? If yes then continue reading. Otherwise you may if you wish to.
Following questions are only for those who are very much confident about their knowledge on java synchronization. I bet few of us can answer all these questions correctly.

Given the codes,
MyIO.java

public class MyIO {
    public synchronized void read() {
        System.out.println("Reading started....");
        for (int i = 0; i < 10; i++) {
            System.out.println("Read " + i);
            try {
                // sleeps for 0 to 2 milliseconds.
                Thread.sleep(Math.round(Math.random() * 2));
            } catch (InterruptedException e) {
                ;// no operation
            }
        }
        System.out.println("Reading completed.");
    }
    public synchronized void write() {
        System.out.println("Writing started....");
        for (int i = 0; i < 10; i++) {
            System.out.println("Write " + i);
            try {
                // sleeps for 0 to 2 milliseconds.
                Thread.sleep(Math.round(Math.random() * 2));
            } catch (InterruptedException e) {
                ;// no operation
            }
        }
        System.out.println("Writing completed.");
    }
}

Reader.java

public class Reader implements Runnable {
    private final MyIO io;
    public Reader(MyIO io) {
        super();
        this.io = io;
    }
    public void run() {
        io.read();
    }
}

Writer.java

public class Writer implements Runnable {
    private final MyIO io;
    public Writer(MyIO io) {
        super();
        this.io = io;
    }
    public void run() {
        io.write();
    }
}

Q1: Select all possible output of the following program.

public class ThreadRunner {
    public static void main(String[] args) {
        MyIO io1 = new MyIO();
        MyIO io2 = new MyIO();
        Thread readThread = new Thread(new Reader(io1));
        Thread writeThread = new Thread(new Writer(io2));
        writeThread.start();
        readThread.start();
    }
}

Options:
a)
Writing started....
Write 0
Reading started....
Read 0
Read 1
Write 1
...
...
Write 8
Write 9
Reading completed.
Writing completed.

b)
Writing started....
Write 0
Reading started....
Read 0
Write 1
Read 1
Write 2
...
...
Read 8
Read 9
Write 7
Write 8
Reading completed.
Write 9
Writing completed.

c)
Writing started....
Write 0
Write 1
...
...
Write 8
Write 9
Writing completed.
Reading started....
Read 0
Read 1
...
...
Read 8
Read 9
Reading completed.

d) None of the above

Q2: Select all possible output of the following program.

public class ThreadRunner {
    public static void main(String[] args) {
        MyIO io = new MyIO();
        Thread readThread = new Thread(new Reader(io));
        Thread writeThread = new Thread(new Writer(io));
        writeThread.start();
        readThread.start();
    }
}

Options:
a)
Writing started....
Write 0
Write 1
...
...
Write 8
Write 9
Writing completed.
Reading started....
Read 0
Read 1
...
...
Read 8
Read 9
Reading completed.

b)
Reading started....
Read 0
Read 1
...
...
Read 8
Read 9
Reading completed.
Writing started....
Write 0
Write 1
...
...
Write 8
Write 9
Writing completed.

c)
Writing started....
Write 0
Reading started....
Read 0
Write 1
Read 1
Write 2
...
...
Read 8
Read 9
Write 7
Write 8
Reading completed.
Write 9
Writing completed.

d) None of the above.

Q3: What will be the output of the following program if both MyIO.read() and MyIO.write() are made static?

public class ThreadRunner {
    public static void main(String[] args) {
        MyIO io1 = new MyIO();
        MyIO io2 = new MyIO();
        Thread readThread = new Thread(new Reader(io1));
        Thread writeThread = new Thread(new Writer(io2));
        writeThread.start();
        readThread.start();
    }
}

Options:
a)
Writing started....
Write 0
Write 1
...
...
Write 8
Write 9
Writing completed.
Reading started....
Read 0
Read 1
...
...
Read 8
Read 9
Reading completed.

b)
Reading started....
Read 0
Read 1
...
...
Read 8
Read 9
Reading completed.
Writing started....
Write 0
Write 1
...
...
Write 8
Write 9
Writing completed.

c)
Writing started....
Write 0
Reading started....
Read 0
Write 1
Read 1
Write 2
...
...
Read 8
Read 9
Write 7
Write 8
Reading completed.
Write 9
Writing completed.

d) None of the above.

Answers:

1: Correct answers are A, B and C. A and B are correct because both of the threads readThread and writeThread are working on two different instances of MyIO. So in this case object level synchronization has NO effect. Again we all know that it is the JVM who decides which thread will get chance to run. In case of C, JVM may decide to let writeThread to finish its job before it starts readThread. So C is also a valid answer.

2: Correct answers are A and B. In this case note that both of the threads are working on same instance. Object level synchronization will be applied is this scenario. So the thread that gets started first will make the other thread wait until it finishes its job.

3: Correct answers are A and B. Note that both MyIO.read and MyIO.write are declared as static. Even though both threads work in two different instances of class MyIO, object level synchronization has no effect. Class level synchronization will take effect in this case.

Note: The first two paragraph of this post is just to attract your attention. Please don’t take it other ways.

Comments (2)

English to Bengali dictionary for mobile

I am happy to announce the initial release of English 2 Bengali Dictionary designed for mobile. Bangla dictionary is now on your pocket and is free. I have used Sun Java Wireless Toolkit 2.5.2 with Mobile Tools for the Java Platform (MTJ), an extention to Eclipse frameworks, to develop this application.

Installation:
Browse http://weaverspark.com/java/mobile/dictionary/download.php from your mobile. This will start the installation of the application.

Please read all the comments below if you face any problem installing this application. I hope you will find your answers to your problem.

Supported Platform:
This application should run on any mobile that supports CLDC 1.1 and MIDP 2.0. This application is tested on Nokia 3110c and Nokia 6300.

Features:
1. This application can be configured to run both online and offline. Default configuration is to access necessary raw data online.
2. GRE Word Filtering can be enabled to view words that appear on Barron’s GRE Word book. This will be helpful to those who are preparing for GRE and want to know the meaning of words that starts with ‘a’, for example.

To access the dictionary offline:
Default configuration need internet connection when you want to find meaning for any word. To be able to find meaning when you are offline (not connected to internet) all files or raw data that are used should be downloaded from the URL ‘http://weaverspark.com/downloads/java/mobile/dictionary/BanglaDictionary.zip‘ to the memory card of your mobile. All the directory contents from ‘A’ to ‘Z’ should be downloaded. Let us assume that all the folders are downloaded/copied to the folder ‘dictionary’ of your mobile’s memory card. Now start the application and go to ‘Settings’ window for this application and change the value in ‘Raw Data URL‘ field that locates to the dictionary folder of your memory card. In most cases mobile’s memory card is assigned the drive letter ‘E’. So in this case our final URL should be ‘file:///E:/dictionary/‘. Dont forget to Save these settings. Optionally you can change the attribute of the ‘dictionary’ folder to hidden so that other application of your mobile do not find this folder.

Please click here for more help regarding Raw Data URL value.

This application is not signed by any trusted CA. Please let me know if any one can help me in this regard.

I would be thankful to those who give me valuable feedback to improve this application. Thanks in advance to all of you for using my application.

Comments (314)

Efficient way to work with JDBC (template style)

Writing reusable codes has always been a great challange for any developer. We, as java developers always are concerned to write reusable codes. But not always we end up with reusable codes. I hope all java developers who worked with JDBC have discovered such situations when we end up with duplicate codes that are used to releaes resources like ResultSet, Statement and Connection objects. I will try to discuss on the solutions to this problem in this article. Best ways to work with JDBC is beyond the scope this discussion.

Let us first look at the following code snippet that is used to read some information from a table of a database. Here we are first creating a database connection. Obtaining Statement object from the Connection. Then we get a ResultSet object to work with by executing the statement. Care must be taken to release these resources properly.


public void someMethod() {
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
String url = "jdbc:mysql://localhost:3306/";
String dbName = "jdbctutorial";
String driver = "com.mysql.jdbc.Driver";
String userName = "root";
String password = "root";
try {
Class.forName(driver).newInstance();
conn = DriverManager.getConnection(url+dbName,userName,password);
stmt = conn.createStatement();
rs = stmt.executeQuery("Select * from MyTable");
// do some work with this result set
} catch (Exception e) {
e.printStackTrace();
} finally {
if (rs != null) {
rs.close();
}
rs = null;
if (stmt != null) {
stmt.close();
}
stmt = null;
if (conn != null) {
conn.close();
}
conn = null;
}
}

Every time we are to write code to add more functionality to the application, we need to write code to obtain connection,prepare statement, execute, handle result set and at last release resources. Obtaining connection, preparing statements,and releasing resources are the common steps and this is where we end up with duplicate codes.

It is time to apply Abstraction and Encapsulation to make our code more flexible. We will apply abstraction to the codes that are used to create/obtain database connection. Again we will apply encapsulation to the codes that processes the ResultSet obtained by executing the statement. Here is our new codes that uses a different kind of approach to do read/write operation to the database.

Let us now have a look at the following example. This is a DAO implementation which has two methods. First method addCompany(Company) is used to add new Company and the second one List listCompany() is used to get the list of existing companies. Note that we are not dealing with connection and statements here. We dont need to worry about opening and closing the connection and releasing resources like Statements and ResultSets. Everything is being taken care of by JDBCTemplate implementation.The first statement of addCompany is creating a new instance of a sub-class of UpdateStatement. The overriden handleGeneratedKeys(ResultSet) method will be called when executeUpdate of JDBCTemplate gets executed. Similarly in getCompanyList() the overriden method UpdateStatement.handleResultSet(ResultSet) gets executed as a callback method by JDBCTemplate.executeUpdate(). The codes are now much cleaner.

public class CompanyDaoImpl implements CompanyDao {
public void saveCompany(Company company) {
try {
UpdateStatement stmt = new UpdateStatement() {
public void handleGeneratedKeys(ResultSet rs) {
// Add codes to retrieve and use the generated id....
}
};
String sql = "Insert into company_list(name, code, type) values(?,?,?)";
Object[] parameters = new Object[] { company.getName(),
company.getCode(), company.getType() };
int[] sqlTypes = new int[] { Types.VARCHAR, Types.VARCHAR, Types.VARCHAR };
new JDBCTemplate()
.executeUpdate(sql, Statement.RETURN_GENERATED_KEYS,
parameters, sqlTypes, stmt);
} catch (SQLException e) {
System.out.println(e.getMessage());
}
}
public List getCompanyList(String username) {
final List companyList = new ArrayList();
try {
SelectStatement stmt = new SelectStatement() {
public void handleResultSet(ResultSet rs) throws SQLException {
while (rs.next()) {
Company company = new Company();
company.setId(rs.getLong(1));
company.setName(rs.getString(2));
company.setCode(rs.getString(3));
company.setType(rs.getString(4));
companyList.add(company);
}
}
};
new JDBCTemplate()
.executeQuery(
"Select C.id, C.name, C.code, C.type"
+ " from company_list C
+ " where C.username=?)",
new Object[] { username }, new int[] {Types.VARCHAR}, stmt);
} catch (SQLException e) {
System.out.println(e.getMessage());
}
return companyList;
}
}

The description of other helper classes used in the above example are given below.

1. ConnectionContext
This class is an abstraction to the codes that are used to connect to the database.

package com.jaywalkable.dsepop.dao.impl;
import java.sql.Connection;
import java.sql.SQLException;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
public class ConnectionContext {
public static Connection getConnection() throws SQLException {
Connection conn = null;
try {
Context initContext = new InitialContext();
Context envContext = (Context) initContext.lookup("java:/comp/env");
DataSource ds = (DataSource) envContext.lookup("jdbc/TestDB");
conn = ds.getConnection();
} catch (NamingException e) {
// notify the error here....
}
return conn;
}
}

2. SelectStatement
The implementation of this interface is used to handle/process ResultSet object that we get after executing any statement that returns a ResultSet object.

package com.jaywalkable.dsepop.dao.jdbc;
import java.sql.ResultSet;
import java.sql.SQLException;
public interface SelectStatement {
public void handleResultSet(ResultSet rs) throws SQLException;
}

3. UpdateStatement
The sub-classes of this class are responsible to handle/process any keys that are generated because of any insert statement. This class can be used to send any update statements to the database.

package com.jaywalkable.dsepop.dao.jdbc;
import java.sql.ResultSet;
public class UpdateStatement {
public void handleGeneratedKeys(ResultSet rs) {
}
}

4. This is the core interface of this API. Implementation of this interface is mainly responsible to minimize or help us to write reusable codes.

package com.jaywalkable.dsepop.dao.jdbc;
import java.sql.SQLException;
public interface SQLTemplate {
public void addBatch(String sql, Object[] parameters, int[] sqlTypes) throws SQLException;
public void beginTransaction() throws SQLException;
public void commit() throws SQLException;
public int[] executeBatch() throws SQLException;
public void executeQuery(String sql, Object[] parameters, int[] sqlTypes,
SelectStatement command) throws SQLException;
public int executeUpdate(String sql, int autoGeneratedKeys,
Object[] parameters, int[] sqlTypes, UpdateStatement command) throws SQLException;
public void rollback() throws SQLException;
}

5.JDBCTemplate
This is the implementation of the above interface.

package com.jaywalkable.dsepop.dao.jdbc;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import com.jaywalkable.dsepop.dao.impl.ConnectionContext;
public class JDBCTemplate implements SQLTemplate {
boolean isAutoCommit = true;
Connection conn = null;
PreparedStatement prepStmt = null;
public JDBCTemplate() {
super();
}
public void addBatch(String sql, Object[] parameters, int[] sqlTypes)
throws SQLException {
setParameters(prepStmt, parameters, sqlTypes);
}
public void beginTransaction() throws SQLException {
this.isAutoCommit = false;
getConnection().setAutoCommit(this.isAutoCommit);
}
public void commit() throws SQLException {
try {
this.conn.commit();
this.isAutoCommit = true;
} catch (SQLException e) {
this.conn.rollback();
throw e;
} finally {
closeConnection();
}
}
public int[] executeBatch() throws SQLException {
if (prepStmt != null) {
int[] updateCounts = prepStmt.executeBatch();
closeResources(null, prepStmt);
prepStmt = null;
return updateCounts;
}
closeConnection();
return new int[0];
}
public void executeQuery(String sql, Object[] parameters, int[] sqlTypes,
SelectStatement command) throws SQLException {
PreparedStatement stmt = getConnection().prepareStatement(sql);
setParameters(stmt, parameters, sqlTypes);
ResultSet rs = stmt.executeQuery();
command.handleResultSet(rs);
closeResources(rs, stmt);
rs = null;
stmt = null;
}
public int executeUpdate(String sql, int autoGeneratedKeys,
Object[] parameters, int[] sqlTypes, UpdateStatement command)
throws SQLException {
PreparedStatement stmt = getConnection().prepareStatement(sql);
setParameters(stmt, parameters, sqlTypes);
int count = stmt.executeUpdate(sql, autoGeneratedKeys);
ResultSet keys = null;
if (Statement.RETURN_GENERATED_KEYS == autoGeneratedKeys) {
keys = stmt.getGeneratedKeys();
command.handleGeneratedKeys(keys);
}
closeResources(keys, stmt);
keys = null;
stmt = null;
return count;
}
public void rollback() throws SQLException {
try {
this.conn.rollback();
this.isAutoCommit = true;
} catch (SQLException e) {
throw e;
} finally {
closeConnection();
}
}
private void closeConnection() {
if (this.conn != null) {
try {
this.conn.close();
} catch (SQLException e) {
;
}
this.conn = null;
}
}
private void closeResources(ResultSet rs, Statement stmt) {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
;
}
}
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
;
}
}
if (this.isAutoCommit) {
closeConnection();
}
}
private Connection getConnection() throws SQLException {
if (this.conn != null) {
this.conn = ConnectionContext.getConnection();
}
return this.conn;
}
private void setParameters(PreparedStatement stmt, Object[] parameters,
int[] sqlTypes) throws SQLException {
for (int i = 0; i < parameters.length; i++) {
Object value = parameters[i];
int sqlType = sqlTypes[i];
int position = i + 1;
stmt.setObject(position, value, sqlType);
}
}
}

Comments (1)