Question

I'm attempting to write a flexible Class that will allow me to parse Binary Data Structures, using Classes defined in Java.

When I'm working purely with int variables, I'm able to achieve what I want, but as soon as I move on to use something like byte[] as a type, I stumble. See the below example.

public class ReflectionTest {
    public ReflectionTest(MappedByteBuffer buffer, int start) {
        buffer.position(start);
        Field[] fields = this.getClass().getDeclaredFields();
        try {
            for (Field field : fields) {
                if (field.getType().toString().equals("int")) {
                    //Set the value of the int field
                    field.setInt(this, buffer.getInt());
                } else if (field.getType().toString().equals("class [B")) {
                    //Set the value of the byte array...
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

public class ReflectionTest1 extends ReflectionTest {
    public byte[] Signature = new byte[4];
    public byte[] Version = new byte[4];
    public int Time;

    public ReflectionTest1(MappedByteBuffer buffer, int start) {
        super(buffer,start);
    }
}

public Main() {
    try {
        FileChannel channel = new RandomAccessFile("test.bin", "r").getChannel();
        MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size());
        buffer.order(ByteOrder.LITTLE_ENDIAN);
        ReflectionTest1 test = new ReflectionTest1(buffer,0);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

I'm stumped as to how I can either get the length of the arrays defined in ReflectionTest1 (for example, Signature has a length of 4), and thus read in the correct amount of data from the provided MappedByteBuffer to the field.

Is this even possible in Java? My reasoning is that I have a number of structures, some of which have a large number of elements. Instead of repeating myself (performing a getInt/get per field), I could use Reflection to automatically populate the sub classes fields based upon their type, and length.

There are numerous libraries out there that provide similar functionality, but none that provide the flexibility that I require (at least, from what I could find).

Any assistance or insight is gratefully received! :)

Was it helpful?

Solution

To access arrays reflectively use java.lang.reflect.Array.

Your code should then read:

 if (int.class.equals(field.getType()) 
 {
   ...
 } 
 else if (field.getType().isArray() && byte.class.equals(field.getType().getComponentType()))
 {
   ...
 }

On the assumption that you don't want to read the whole buffer into the byte array, how you know what size the array is will be proprietary to your serialization mechanism (which will probably make the switch statement invalid - it should be replaced with a switch on values read from the buffer).

A common approach is to write the type first, which then controls how to interpret what comes next. In the case of an array, the what comes next would be the length and then the array content.

In all honesty you are better off using a 3rd party library such as Google's Protocol Buffers, which already covers this and much more.

OTHER TIPS

Look at java.lang.reflect.Array, it has all the methods needed to access the length and the individual elements of an array.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top