Thrift: Reading Thrift Objects from Disk with Java
02/05/2009
Reading Thrift objects is as easy as writing them to disk. Here's the utility class I use for reading one or more Thrift objects (of the same type) serialized to disk:
importjava.io.BufferedInputStream;importjava.io.File;importjava.io.FileInputStream;importjava.io.FileNotFoundException;importjava.io.IOException;importcom.facebook.thrift.TBase;importcom.facebook.thrift.TException;importcom.facebook.thrift.protocol.TBinaryProtocol;importcom.facebook.thrift.transport.TIOStreamTransport;/**
* A simple class for reading Thrift objects (of a single type) from a file.
*
* @author Joel Meyer
*/publicclassThriftReader{/**
* Thrift deserializes by taking an existing object and populating it. ThriftReader
* needs a way of obtaining instances of the class to be populated and this interface
* defines the mechanism by which a client provides these instances.
*/publicstaticinterfaceTBaseCreator{TBasecreate();}/** File containing the objects. */protectedfinalFilefile;/** Used to create empty objects that will be initialized with values from the file. */protectedfinalTBaseCreatorcreator;/** For reading the file. */privateBufferedInputStreambufferedIn;/** For reading the binary thrift objects. */privateTBinaryProtocolbinaryIn;/**
* Constructor.
*/publicThriftReader(Filefile,TBaseCreatorcreator){this.file=file;this.creator=creator;}/**
* Opens the file for reading. Must be called before {@link read()}.
*/publicvoidopen()throwsFileNotFoundException{bufferedIn=newBufferedInputStream(newFileInputStream(file),2048);binaryIn=newTBinaryProtocol(newTIOStreamTransport(bufferedIn));}/**
* Checks if another objects is available by attempting to read another byte from the stream.
*/publicbooleanhasNext()throwsIOException{bufferedIn.mark(1);intval=bufferedIn.read();bufferedIn.reset();returnval!=-1;}/**
* Reads the next object from the file.
*/publicTBaseread()throwsIOException{TBaset=creator.create();try{t.read(binaryIn);}catch(TExceptione){thrownewIOException(e);}returnt;}/**
* Close the file.
*/publicThriftReaderclose()throwsIOException{bufferedIn.close();returnthis;}}
This class is useful if you've got a file containing a list of Thrift objects of the same type. Let's say you had a Thrift object called Album and a file containing a list of these Album objects. To read the file you'd do this:
// Create the reader
ThriftReaderthriftIn=newThriftReader(newFile("/some/thrift/file.thrifty",newThriftReader.TBaseCreator(){@OverrideTBasecreate(){returnnewAlbum();}});// Open it
thriftIn.open();// Read objects
List<Album>albums=newArrayList<Album>();while(thriftIn.hasNext()){albums.add((Album)thriftIn.read());}// Close reader
thriftIn.close();
As mentioned in the post on writing Thrift objects, TBase is the interface all Thrift objects implement that provides the read(...) and write(...) methods. When you're dealing with generated files you're limited to the code that's generated, so in this case I opted to use the TBase interface since that at least guarantees that the read and write methods will exist. I thought about making the class generic and casting to TBase, but then it's not clear (well, not contractually enforced) that the class is expecting a Thrift object. The downside of my method is that you have an unchecked cast, which I'm not a fan of.
comments powered by Disqus