Tech and Media Labs
This site uses cookies to improve the user experience.


RionReader

Jakob Jenkov
Last update: 2019-09-21

The RION Ops RionReader class, com.nanosai.rionops.rion.read.RionReader makes it easy to write RION fields from a Java byte array. In this RionReader tutorial we will see how to use the RionReader.

Create a RionReader

You create a RionReader via its constructor. Here is an example of creating a RionReader:

RionReader rionReader = new RionReader();

Set Source

To read RION fields with a RionReader you must first set a source byte array on the RionReader. Setting a source byte array is done via the method setSource(). Here is an example of setting the source byte array on a RionReader via its setSource() method:

byte[] source = ... //get byte array with RION fields from somewhere
int sourceOffset = 0;
int sourceLength = 124;
RionReader rionReader = new RionReader();

rionReader.setSource(source, sourceOffset, sourceLength);

The setSource() method takes 3 parameters. The first is the source byte array itself. The second parameter is the byte offset into the byte array to start reading RION fields from. The third parameter is the length in bytes of the RION fields to read - the total number of bytes of all RION fields the RionReader is to read.

Full RionReader Read Example

// First we write some RION fields to a byte array

byte rionFields = new byte[1024 * 1024];
int  startOffset = 0;

RionWriter rionWriter = new RionWriter();
rionWriter.setDestination(rionFields, startOffset);

rionWriter.writeInt64(123);
rionWriter.writeFloat64(987.654);
rionWriter.writeUtf8("Rion Ops Example");

int totalBytesWritten = rionWriter.index - startOffset;


// Second we read the written RION fields:

RionReader rionReader = new RionReader();
rionReader.setSource(rionFields, startOffset, totalBytesWritten);

while(rionReader.hasNext()) {
    rionReader.nextParse();

    int rionFieldType = rionReader.fieldType;

    switch(rionFieldType) {

        case RionFieldTypes.INT_POS : ;
        case RionFieldTypes.INT_NEG : {
            long fieldValue = rionReader.readInt64() ;
            break;
        }
        case RionFieldTypes.FLOAT : {
            double fieldValue = rionReader.readFloat64();
            break;
        }
        case RionFieldTypes.UTF_8 : {
            String fieldValue = rionReader.readUtf8AsString();
            break;
        }
    }
}

This example first writes a few RION fields into a byte array using a RionWriter. Then it notes how many bytes the RION fields written fill in length.

Second, this example creates a RionReader and sets the destination byte array of the RionWriter as source byte array of the RionReader. The start offsets into the array is the same for both RionWriter and RionReader. The source array length is set to the number of bytes written by the RionWriter.

Third, the example loops as long as hasNext() returns true, and iterates through all the RION fields in the source byte array, one by one.

Read Bytes

You can read a RION Bytes field using the RionReader readBytes() method. The readBytes() takes a byte array as parameter. The readBytes() method will read the bytes of the RION Bytes field into this byte array. Here is an example of reading a RION Bytes field with the readBytes() method:

byte[] dest = new byte[1024];

int bytesRead = rionReader.readBytes(dest);

The value returned by the readBytes() method is the number of bytes read into the destination byte array.

The readBytes() method also comes in a version where you can specify the offset into the destination byte array to start writing the Bytes field value, and a maximal length (number of bytes) to read. Here is an example of reading a RION Bytes field using that readBytes() method:

byte[] dest = new byte[1024];

int bytesRead = rionReader.readBytes(dest, 2, 10);

This example tells the readBytes() method to start writing the Bytes field value into the destination array from offset 2, and to maximally read 10 bytes.

Read Boolean

To read a RION Boolean field you can use the RionReader readBoolean() method. Here is an example of reading RION Boolean field using the RionReader readBoolean() method:

boolean aBoolean = rionReader.readBoolean();

You can also read the RION Boolean field as a Java Boolean object. This is necessary if the RION Boolean field can have a null value in your case. Here is an example of reading a Java Boolean object using the RionReader readBooleanObj() method:

Booelean aBoolean = rionReader.readBooleanObj();

Read Int64

To read a RION Int64 field you can use the RionReader readInt64() method. Here is an example of reading a RION Int64 field using the RionReader readInt64() method:

long int64 = rionReader.readInt64();

The RionReader also has a method that can read RION Int64 fields into a Java Long object. This way, you can see if the RION Int64 field was set to null - in case your specific use case allows that. Here is an example of reading a RION Int64 field into a Java Long object using the RionReader readInt64Obj() method:

Long int64 = rionReader.readInt64Obj();

Read Float32 and Float64

The RionReader has two methods to read RION Float fields as either a Java float or Java double value. These methods are named readFloat32() and readFloat64() Here are two examples of reading a RION Float field into a Java float and double variable:

float  float32 = rionReader.readFloat32();
double float64 = rionReader.readFloat64();

There are also two versions of these methods that read RION Float fields into a Java Float and Java Double object. These methods are named readFloat32Obj() and readFloat64Obj(). Here are two examples of reading a RION Float field into a Java Float and Java Double object:

Float  float32 = rionReader.readFloat32Obj();
Double float64 = rionReader.readFloat64Obj();

Use the readFloat32Obj() or readFloat64Obj() methods if the RION Float field can be set to null in your concrete use case.

Float32 or Float64?

A RION Float field can contain either a 32 bit or 64 bit floating point number. The way you see if the RION Float field contains one or the other is by looking at the RionReader fieldLength field. If the fieldLength field is 4, the RION Float field contains a 32 bit (4 byte) floating point number. If the fieldLength field is 8, the RION Float field contains a 64 bit (8 byte) floating point number.

Read UTF-8

The RionReader class has a method named readUtf8String() which can read a RION UTF-8 field into a Java String. Here is an example of reading a RION UTF-8 field into a Java String with readUtf8String() :

String utf8 = rionReader.readUtf8String();

Read UTC

The readUtcCalendar() method of the RionReader class can read a RION UTC field as a
Java Calendar instance. Here is an example of reading a RION UTC field as a Java Calendar:

Calendar utcTime = rionReader.readUtcCalendar();

Read Composite RION Fields

RION has 3 composite field types. By composite field types we mean RION fields which can contain other RION Fields nested inside them. The composite RION field types are:

  • RION Array
  • RION Table
  • RION Object

Since these RION field types can contain nested fields, you need to "move into" these fields to read the nested fields. When you are done reading all the nested fields, you need to "move out of" these fields again. Moving into and out of a composite RION field moves the RionReader one nesting level in, and one nesting level out. This will be explained in more detail in the following sections.

moveInto() and moveOutOf()

When reading a composite RION field you need to use the RionReader moveInto() and moveOutOf() methods.

The moveInto() method will move the RionReader's internal state "into" the given RION field. That means, that the hasNext() method now returns true as long as the RION field you moved into has more nested fields.

The moveOutOf() method moves the RionReader's internal state "out of" the given RION field. Now the hasNext() method will return true if the parent scope (parent RION field or the total source byte array for the RionReader) has more RION fields.

Here is a simple RION field structure with nested fields to illustrate this mechanism:

RION IntPos
RION UTF-8
RION Object
    - RION UTF-8
    - RION Float
RION IntNeg

At the outer nesting level (top level) of the above RION field sequence, the RionReader hasNext() will return true, as long as there are RION fields at this nesting level. That means 4 times true in the example above.

At the third RION field (the RION Object) field, you "move into" the RION Object field. Now the RionReader hasNext() method returns true 2 times, because there are 2 nested RION fields inside the RION Object field. Once the hasNext() method returns false, you "move out of" the composite RION field again. Actually, you can "move out of" a composite RION field whenever you are done with it. You don't need to parse all its nested fields first.

Here is how the code could look for reading the above RION structure (as a draft):

rionReader.nextParse();
long numberPos = rionReader.readInt64();

rionReader.nextParse();
String text = rionReader.readUtf8String();

rionReader.nextParse();

rionReader.moveInto();

  rionReader.nextParse();
  String objText = rionReader.readUtf8String();

  rionReader.nextParse();
  double objDbl  = rionReader.readFloat64();

rionReader.moveOutOf();

rionReader.nextParse();
long numberNeg = rionReader.readInt64();

Here is another example which uses while loops to iterate the RION fields:

while(rionReader.hasNext()) {
    rionReader.nextParse();

    if(rionReader.fieldType == RionFieldTypes.INT_POS) {
        long numberPos = rionReader.readInt64();
    }
    if(rionReader.fieldType == RionFieldTypes.INT_NEG){
        long numberNeg = rionReader.readInt64();
    }
    if(rionReader.fieldType == RionFieldTypes.UTF_8) {
        String text = rionReader.readUtf8String();
    }
    if(rionReader.fieldType == RionFieldTypes.OBJECT {
        rionReader.moveInto();

        while(rionReader.hasNext()) {
            rionReader.nextParse();

            //read nested fields.

        }
        rionReader.moveOutOf();
    }

}

You can improve on the above code in various ways - e.g. by using a Java switch statement instead of the Java if statements. However, the above code serves mostly to demonstrate how to navigate composite RION fields with the RionReader.

Jakob Jenkov




Copyright  Jenkov Aps
Close TOC