Technical Blog Post
Abstract
Character Conversion in Java 8
Body
Character Conversion in Java 8
This article will provide information about JRE 8 package java.nio.charset for the conversion from character to byte and from byte to character.
Starting from JRE 1.8 the package sun.io converter removed so user should use java.nio.charset package for character conversion in their application. This article is applicable in general and also for customer using Db2Connect Java driver "IBM Data Server driver for JDBC and SQLJ "
1) Example of Character to byte conversion while inserting characters to Server.
public class JavaNIOCharToByteConverter
{
private java.nio.CharBuffer charBuffer;
private java.nio.charset.CharsetEncoder encoder;
private String encoding;
private int nextByteIndex;
private int nextCharIndex;
protected JavaNIOCharToByteConverter (String encoding, boolean doNotReportError) throws
java.io.UnsupportedEncodingException
{
encoder = java.nio.charset.Charset.forName (encoding).newEncoder ();
encoder.onMalformedInput (doNotReportError ? java.nio.charset.CodingErrorAction.REPLACE : java.nio.charset.CodingErrorAction.REPORT);
encoder.onUnmappableCharacter (doNotReportError ? java.nio.charset.CodingErrorAction.REPLACE : java.nio.charset.CodingErrorAction.REPORT);
encoding = encoding;
nextByteIndex = 0;
nextCharIndex = 0;
}
public int convert (char[] input, int inOff, int inEnd, byte[] output, int outOff, int outEnd) throws
java.nio.charset.CharacterCodingException
{
int inputLength = inEnd - inOff;
if (charBuffer == null) {
charBuffer = java.nio.CharBuffer.allocate(inputLength);
}
else if (charBuffer.capacity() < inputLength)
{
charBuffer = java.nio.CharBuffer.allocate (inputLength);
}
// clear the buffer, position is 0, limit is the capacity
charBuffer.clear();
// position is the input (inEnd - inOff)
charBuffer.put (input, inOff, inEnd);
// limit is set to position, position is set to 0
charBuffer.flip();
nextCharIndex = inOff;
nextByteIndex = outOff;
java.nio.ByteBuffer byteBuffer = java.nio.ByteBuffer.wrap (output, outOff, outEnd-outOff).slice();
java.nio.charset.CoderResult result = encoder.encode (charBuffer, byteBuffer, true);
nextCharIndex += charBuffer.position();
// limit is set to position, posiition is set to 0
byteBuffer.flip();
nextByteIndex += byteBuffer.limit();
if (result.isError() || result.isOverflow())
result.throwException();
return byteBuffer.limit();
}
// called after convert call
public int flush (byte[] outByteBuffer, int offset, int outEnd) throws
java.nio.charset.CharacterCodingException
{
java.nio.ByteBuffer byteBuffer = java.nio.ByteBuffer.wrap(outByteBuffer, offset, outEnd-offset).slice();
java.nio.charset.CoderResult result = encoder.flush (byteBuffer);
// limit is set to position, posiition is set to 0
byteBuffer.flip();
nextByteIndex += byteBuffer.limit();
if (result.isError() || result.isOverflow())
result.throwException();
return byteBuffer.limit();
}
}
2) Example of Bytes to character conversion while reading characters from Server.
public class JavaNIOByteToCharConverters
{
private java.nio.ByteBuffer byteBuffer;
private java.nio.charset.CharsetDecoder decoder;
private String encoding;
private int nextByteIndex;
private int nextCharIndex;
protected JavaNIOByteToCharConverters (String encoding,boolean alternateUTF8Encoding, boolean doNotReportError) throws java.io.UnsupportedEncodingException
{
//JDK 8 follows strict UTF8 encoding ,"UTF8J" retains relaxed UTF8 encoding
if(alternateUTF8Encoding==true &&
(encoding.equalsIgnoreCase("UTF8" ) || encoding.equalsIgnoreCase("UTF-8" ) || encoding.equalsIgnoreCase("UTF_8" )) )
encoding ="UTF8J";
decoder = java.nio.charset.Charset.forName (encoding).newDecoder ();
decoder.onMalformedInput (doNotReportError ? java.nio.charset.CodingErrorAction.REPLACE : java.nio.charset.CodingErrorAction.REPORT);
decoder.onUnmappableCharacter (doNotReportError ? java.nio.charset.CodingErrorAction.REPLACE : java.nio.charset.CodingErrorAction.REPORT);
encoding = encoding;
nextByteIndex = 0;
nextCharIndex = 0;
}
public int convert (byte[] rawBytes, int byteOffset, int byteEnd, char[] output, int charOffset, int charEnd) throws java.nio.charset.MalformedInputException, java.nio.BufferOverflowException, java.nio.charset.UnmappableCharacterException, java.nio.charset.CharacterCodingException
{
//first pass, initialize ByteBuffer
if (byteBuffer == null) byteBuffer = java.nio.ByteBuffer.allocate (byteEnd - byteOffset + 3);
int spareBytesPosition = byteBuffer.position ();
//increase ByteBuffer if needed.
if (byteBuffer.limit () < (byteEnd - byteOffset)) {
java.nio.ByteBuffer newBB = java.nio.ByteBuffer.allocate (byteEnd - byteOffset + byteBuffer.position () + 3);
byteBuffer.flip ();
while (byteBuffer.position () < byteBuffer.limit ())
newBB.put (byteBuffer.get ());
byteBuffer = newBB;
}
byteBuffer.put (rawBytes, byteOffset, byteEnd - byteOffset);
byteBuffer.flip ();
java.nio.CharBuffer charBuffer = java.nio.CharBuffer.wrap (output, charOffset, charEnd - charOffset).slice ();
java.nio.charset.CoderResult result = null;
result = decoder.decode (byteBuffer, charBuffer, false);
nextByteIndex = byteBuffer.position () + byteOffset - spareBytesPosition;
if (result.isError ()) result.throwException ();
if (result == java.nio.charset.CoderResult.UNDERFLOW && (byteBuffer.position () < (byteBuffer.limit ()))) {
byte[] unconvertedBytes = new byte[byteBuffer.limit () - byteBuffer.position ()];
byteBuffer.get (unconvertedBytes);
nextByteIndex = byteBuffer.position () + byteOffset - spareBytesPosition;
byteBuffer.clear ();
byteBuffer.put (unconvertedBytes);
}
else {
byteBuffer.clear ();
}
charBuffer.flip ();
nextCharIndex = charBuffer.limit ();
//to simulate sun.io.ConversionBufferFullException
if (result == java.nio.charset.CoderResult.OVERFLOW) result.throwException ();
return nextCharIndex;
}
public char[] convertAll (byte[] rawBytes) throws java.nio.charset.CharacterCodingException
{
java.nio.ByteBuffer byteBuffer = java.nio.ByteBuffer.wrap (rawBytes);
java.nio.CharBuffer charBuffer = decoder.decode (byteBuffer);
char[] returnVal = new char[charBuffer.limit ()];
charBuffer.get (returnVal);
return returnVal;
}
}
JRE 1.7 or lower version contains sun.io packages so user can use it for character conversion. sun.io.CharToByteConverter is deprecated and removed from JRE 1.8 and higher.
1) Character to byte conversion .
public class SunIOCharToByteConverter
{
private sun.io.CharToByteConverter ctbc;
protected SunIOCharToByteConverter (String encoding) throws
java.io.UnsupportedEncodingException
{
ctbc = sun.io.CharToByteConverter.getConverter (encoding);
}
public int convert (char[] input, int inOffset, int inEnd, byte[] output, int outOffset, int outEnd) throws
java.nio.charset.CharacterCodingException
{
try {
return ctbc.convert(input, inOffset, inEnd, output, outOffset, outEnd);
}
catch (sun.io.MalformedInputException ex) { }
catch (sun.io.UnknownCharacterException ex) { }
catch (sun.io.ConversionBufferFullException ex) { }
return -1;
}
public int flush (byte[] outByteBuffer, int offset, int outEnd) throws
java.nio.charset.CharacterCodingException
{
try {
return ctbc.flush (outByteBuffer, offset, outEnd);
}
catch (sun.io.MalformedInputException ex) {}
catch (sun.io.ConversionBufferFullException ex)
{}
return -1;
}
}
sun.io.ByteToCharConverter is deprecated and removed from JRE 1.8 and higher.
2) Bytes to character conversion while reading characters from Server.
public class SunIOByteToCharConverter
{
private sun.io.ByteToCharConverter btcc;
protected SunIOByteToCharConverter (String encoding) throws java.io.UnsupportedEncodingException
{
btcc = sun.io.ByteToCharConverter.getConverter (encoding);
}
public int convert (byte[] rawBytes, int byteOffset, int byteEnd, char[] output, int charOffset, int charEnd) throws java.nio.charset.CharacterCodingException
{
try{
return btcc.convert (rawBytes, byteOffset, byteEnd, output, charOffset, charEnd);
}
catch (sun.io.MalformedInputException e) { }
catch (sun.io.ConversionBufferFullException e){ }
catch (sun.io.UnknownCharacterException e){ }
return -1;
}
public char[] convertAll (byte[] rawBytes) throws java.nio.charset.MalformedInputException
{
try {
return btcc.convertAll (rawBytes);
}
catch (sun.io.MalformedInputException e) {}
return null;
}
}
Authors:
Kollol k misra (kmisra@rocketsoftware.com)
Db2Connect Architect
Sujan S Ghosh ( sghosh@rocketsoftware.com)
Advisory software engineer, Db2Connect
UID
ibm11142002