tlc-commons-buffer
Overview
The commons buffer classes provide a set of utilities for easily getting and setting data inside of a buffer, usually of a fixed length. These are typically records received in files from mainframe type systems that are not XML, JSON, or comma-delimited. Each record contains data in fixed positions (columns) in the record.
ByteBuffer
The central class provided here is the ByteBuffer. This class provides read and write methods for a number of different kinds of data type to be placed at fixed displacements and lengths in the buffer.
Because data received from IBM systems is often EBCDIC instead of ASCII, each buffer is associated with an encoding scheme so that read and writes will get and store the data in the proper encoding. Strings that are written to the buffer that are in UNICODE are converted to the appropriate single-byte ASCII or EBCDIC code. Strings that are read from the buffer will be converted into UNICODE appropriately based on the buffer encoding.
Integer and longs that are stored in binary can be different endian formats. Each buffer is associated with an endian type for storing this binary data in either big or little endian format. When these numbers are written to the buffer, the proper endian structure is maintained. Similarly for reading numbers from the buffer.
ByteArray instances are actually backed by Java NIO ByteBuffers. As such the memory model supported by Java ByteBuffer instances is available, so the actual buffer can be direct or non-direct. Direct buffers are typically off-heap and so give the user access to non-Java allocated memory allowing for larger buffers and processing buffers that are from memory mapped I/O buffers.
See the Javadoc for all the different read and write methods available.
These include:
- String (character) data -- which can be read from the buffer as numbers or strings. Also numbers (int, long, etc.) can be written to the buffer as character numerics.
- Integer, Long, Short, and Byte
- Packed decimal -- signed and unsigned
Examples:
Create new array and initialize to spaces
byteArray = new ByteArray(200, ByteArray.EBCDIC_CHARSET_NAME); assertTrue(byteArray.getLength() == 200); byteArray.write(" ", 0); assertTrue((byteArray.getArray().value[0] & 0x00ff) == 0x40); byteArray = new ByteArray(200, ByteArray.ASCII_CHARSET_NAME); assertTrue(byteArray.getLength() == 200); byteArray.write(" ", 0); assertTrue((byteArray.getArray().value[0] & 0x00ff) == 0x20);
Write binary data to array
byteArray = new ByteArray(200, ByteArray.EBCDIC_CHARSET_NAME); byte[] value = {0, 1, 2, 3, 4}; byteArray.write(value, 0); byteArray.write(value, 20); ByteArray bytes1 = byteArray.readAsByteArray(0, 5); ByteArray bytes2 = byteArray.readAsByteArray(20, 5); assertTrue(bytes1.equals(bytes2));
Write and read characters from an array into another buffer
byteArray = new ByteArray(20, ByteArray.EBCDIC_CHARSET_NAME); // write "TEST" starting at displacement 10, length 4 (size of string) byteArray.write("TEST", 10); char[] chars = new char[5]; // read "EST" into middle three positions of chars byteArray.read(11, chars, 1, 3); // convert char values to bytes byte[] bytes = new byte[5]; for (int i = 0; i < 5; i++) { bytes[i] = (byte) chars[i]; } // create new array ByteArray testBA = new ByteArray(bytes); // get array into unpacked hex values String value = testBA.readPns(0, 5, false); // verify ASCII "EST" in middle of five positions assertTrue(value.equals("0045535400"));
Similar to sample above, but with EBCDIC
byteArray = new ByteArray(20, ByteArray.EBCDIC_CHARSET_NAME); byteArray.write("TEST", 10); byte[] bytes = new byte[5]; byteArray.read(11, bytes, 1, 3); ByteArray testBA = new ByteArray(bytes); String value = testBA.readPns(0, 5, false); assertTrue(value.equals("00C5E2E300"));
Read full buffer as String
byteArray = new ByteArray(200, ByteArray.ASCII_CHARSET_NAME); byteArray.write("TEST", 0); value = byteArray.readAsString(); assertTrue(value.length() == 200); assertFalse("TEST".equals(value)); assertTrue("TEST".equals(value.substring(0, 4)));
Read value from buffer as String
byteArray = new ByteArray(200, ByteArray.ASCII_CHARSET_NAME); byteArray.write("TEST", 0); value = byteArray.readAsString(0, 4); assertTrue(value.length() == 4); assertTrue("TEST".equals(value));
Read and write double
byteArray = new ByteArray(10); byteArray.write(1.5, 0); double d = byteArray.readAsDouble(0); assertTrue(d == 1.5); byteArray = new ByteArray(10, ByteOrder.LITTLE_ENDIAN); byteArray.write(1.5, 0); double d = byteArray.readAsDouble(0); assertTrue(d == 1.5);
Read and write int
byteArray = new ByteArray(10); byteArray.write(15, 0); int i = byteArray.readAsInt(0); assertTrue(i == 15); byteArray = new ByteArray(10, ByteOrder.LITTLE_ENDIAN); byteArray.write(15, 2); int i = byteArray.readAsInt(2); assertTrue(i == 15);
Read and write long
byteArray = new ByteArray(10); byteArray.write((long) 15, 2); long i = byteArray.readAsLong(2); assertTrue(i == 15); byteArray = new ByteArray(10, ByteOrder.LITTLE_ENDIAN); byteArray.write((long) 15, 2); long i = byteArray.readAsLong(2); assertTrue(i == 15);
Setting, testing, and clearing bits
byte[] ba = new byte[2]; byteArray = new ByteArray(ba); byteArray.setBit(0, (byte) 0x41); byteArray.setBit(1, (byte) 0x01); assertTrue(byteArray.testBit(0, (byte) 0x01)); assertTrue(byteArray.testBit(0, (byte) 0x40)); assertTrue(byteArray.testBit(0, (byte) 0x41)); assertFalse(byteArray.testBit(0, (byte) 0x02)); assertFalse(byteArray.testBit(1, (byte) 0x80)); assertFalse(byteArray.testBit(1, (byte) 0x81)); assertTrue(byteArray.testBit(1, (byte) 0x01)); byteArray.clearBit(0, (byte) 0x40); assertFalse(byteArray.testBit(0, (byte) 0x40));
Write string with trailing null (for C type strings)
byteArray = new ByteArray(12); byteArray.fill((byte) 0xBB); // use write with "true" to get null terminated string // all extra bytes after string value will be set to null for length of write byteArray.write("TEST", 5, 6, true); String value = byteArray.readPns(0, 12, false); assertTrue(value.equals("BBBBBBBBBB544553540000BB")); byteArray.fill((byte) 0xBB); // use write with "false" to get space filled string (if string shorter than length) // all extra bytes after string value will be set to space for length of write byteArray.write("TEST", 5, 6, false); value = byteArray.readPns(0, 12, false); assertTrue(value.equals("BBBBBBBBBB544553542020BB")); // default without "true" or "false" is false byteArray.write("TEST", 5, 6); value = byteArray.readPns(0, 12, false); assertTrue(value.equals("BBBBBBBBBB544553542020BB")); // In EBCDIC, so spaces will be X'40' byteArray = new ByteArray(12, ByteArray.EBCDIC_CHARSET_NAME); byteArray.write("TEST", 5, 6); value = byteArray.readPns(0, 12, false); assertTrue(value.equals("BBBBBBBBBBE3C5E2E34040BB"));