18 Feb 2007

Streams, Readers and Writers

The Nebula3 IO subsystem provides Stream objects as generic data storage- and transfer-channels. Subclasses of stream implement or wrap specific data transfer protocols. Stream classes are usually associated with an URI scheme:
  • "file:" scheme maps to IO::FileStream class
  • "http:" scheme maps to Net::HttpStream class
  • "mem:" scheme maps to IO::MemoryStream class
These are the URI schemes and associated stream classes that Nebula3 provides out of the box for now. Stream objects are usually created through the IO::Server::CreateStream() method, which takes an URI and returns a matching Stream object:

// create a HttpStream and a FileStream object
IO::Server* ioServer = IO::Server::Instance();
Ptr< Stream> httpStream = ioServer->CreateStream("http://www.radonlabs.de/index.html);
Ptr< Stream> fileStream = ioServer->CreateStream("home:readme.txt");

An application may associate its own stream classes with URI schemes using the IO::Server::RegisterUriScheme() method.

Streams only provide generic Read() and Write() methods to read and write chunks of memory. To access stream data in a more convenient way, StreamReader and StreamWriter objects are attached to the stream. Readers and writers provide specialized interfaces for reading or writing specific types of data. The Nebula3 IO subsystem comes with the following reader and writer classes:
  • BinaryReader/Writer: read/write a stream of typed data elements in binary form
  • TextReader/Writer: for reading and writing text data
  • XmlReader/Writer: for reading and writing XML formatted data
Here's a code example to parse a simple XML file from a HTTP server:

// create a stream and attach an XML reader to it
Ptr< Stream> stream = IO::Server::Instance()->CreateStream("http://www.radonlabs.de/books.xml");
Ptr< XmlReader> xmlReader = XmlReader::Create();
xmlReader-> SetStream(stream);

// start reading...
if (xmlReader-> Open())
{
// iterate through "books" xml elements
if (xmlReader-> SetToFirstChild("books")) do
{
// read attributes from current element
String author = xmlReader-> GetString("author");
int year = xmlReader-> GetInt("year");
int numPages = xmlReader->GetInt("pages");
...
}
while (xmlReader-> SetToNextChild("books"));
xmlReader->Close;
}


Other Nebula3 subsystems may provide their own derived StreamReader and StreamWriter classes. For instance, the Messaging subsystem provides a MessageReader and MessageWriter class for serializing message objects.