Flat Buffers - Mutable Buffers



Overview

Whenever we create a Flat Buffers file, it is readonly from there on. We can read this file using the classes provided by flatc which has const accessors. This helps to keep consisting in using flat buffer file across multiple readers. But sometime, we may need to modify a value after reading and require to pass on modified value to next reader. We can achieve it by creating a new flat buffers from scrach which is better and efficient for large changes. In case of small change, Flat Buffers provides a option --gen-mutable to flatc complier

to generate non-const accessors to modify the flatbuffers file as shown below:
flatc --java --gen-mutable theater.fbs

Example

Consider the following schema.

theater.fbs

namespace com.tutorialspoint.theater;

table Theater {
   name:string;
   address:string;
   int mobile;
}
root_type Theater;

Creating Java Classes from fbs File

To use Flat Buffers, we will now using flatc compiler in mutable mode to create the required class from this ".fbs" file. Let us see how to do that −

flatc  --java --gen-mutable theater.fbs

This will create a Theater.java class in com > tutorialspoint > theater folder in current directory. We're using this class in our application similar to as done in Flat Buffers - Schema chapter.

Using Java Classes created from fbs File

First let's create a writer to write the theater information −

TheaterWriter.java

package com.tutorialspoint.theater;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import com.google.flatbuffers.FlatBufferBuilder;

public class TheaterWriter {
   public static void main(String[] args) throws FileNotFoundException, IOException {
      // create a flat buffer builder
      // it will be used to create Theater FlatBuffer
      FlatBufferBuilder builder = new FlatBufferBuilder(1024);

      // create offset for name and address
      int name = builder.createString("Silver Screener");
      int address = builder.createString("212, Maple Street, LA, California");
      
      // create theater FlatBuffers using startTheater() method
      Theater.startTheater(builder);
      // add details to the Theater FlatBuffer
      Theater.addName(builder, name);   
      Theater.addAddress(builder, address);
      Theater.addMobile(builder, 12233345);

      // mark end of data being entered in Greet FlatBuffer
      int theater = Theater.endTheater(builder);

      // finish the builder
      builder.finish(theater);

      // get the bytes to be stored
      byte[] data = builder.sizedByteArray();

      String filename = "theater_flatbuffers_output";
      System.out.println("Saving theater to file: " + filename);
      // write the builder content to the file named theater_flatbuffers_output
      try(FileOutputStream output = new FileOutputStream(filename)){
         output.write(data);
      }
      System.out.println("Saved theater with following data to disk: \n" + theater);
   }
}	

Next, we will have a reader to read the theater information −

TheaterReader.java

package com.tutorialspoint.theater;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.ByteBuffer;

public class TheaterReader {
   public static void main(String[] args) throws FileNotFoundException, IOException {

      String filename = "theater_flatbuffers_output";
      System.out.println("Reading from file " + filename);
      try(FileInputStream input = new FileInputStream(filename)) {
         // get the serialized data
         byte[] data = input.readAllBytes();
         ByteBuffer buf = ByteBuffer.wrap(data);
         // read the root object in serialized data
         Theater theater = Theater.getRootAsTheater(buf);
         // print theater values 
         System.out.println("Name: " + theater.name());
         System.out.println("Address: " + theater.address());
         System.out.println("Mobile: " + theater.mobile());
         
         
         // Update mobile
         theater.mutateMobile(22333341);
         
         // we can write the theater object again to send it further
         // read the updated mobile value
         System.out.println("Updated Mobile: " + theater.mobile());
      }
   }
}

Compile the project

Now that we have set up the reader and the writer, let us compile the project.

mvn clean install

Serialize the Java Object

Now, post compilation, let us execute the writer first −

java -cp .\target\flatbuffers-tutorial-1.0.jar com.tutorialspoint.theater.TheaterWriter

Saving theater to file: theater_flatbuffers_output
Saved theater with following data to disk:
76

Deserialize the Serialized Object

Now, let us execute the reader to read from the same file −

java -cp .\target\flatbuffers-tutorial-1.0.jar com.tutorialspoint.theater.TheaterReader

Reading from file theater_flatbuffers_output
Name: Silver Screener
Address: 212, Maple Street, LA, California
Mobile: 12233345
Updated Mobile: 22333341
Advertisements