Miłosz Orzeł

.net, js, html, arduino, java... no rants or clickbaits.

IBM.WMQ.MQMessage.ReadString and EndOfStreamException

Recently during modification of a program to communicate with WebSphere MQ (v6.0.2.7) I noticed that logs contain some exceptions of type EndOfStreamException. Since the adapter code was rather complex it took a while before I found a trivial cause of the problems ;)

System.IO.EndOfStreamException: Nie można odczytać danych spoza końca
strumienia.
   w System.IO.__Error.EndOfFile()
   w System.IO.BinaryReader.ReadByte()
   w System.IO.BinaryReader.Read7BitEncodedInt()
   w System.IO.BinaryReader.ReadString()
   w IBM.WMQ.MQMessage.ReadString(Int32 length)

The error was reported, because sometimes in two different locations there was a call to ReadString method on the same MQMessage object:

string text = message.ReadString(message.MessageLength);

To get rid of the trouble simply add one line of code:

string text = message.ReadString(message.MessageLength);
message.Seek(0);

What's the problem?

ReadString is a method that scans stream of bytes and converts it to a string*. After successful reading of entire message content, marker of current position was left on the end of a stream. So next call to ReadString had to end up with EndOfStreamException exception. Why it had to happen? Internally ReadString (IBM.WMQ.MQMessage) uses data stored in MemoryStream object. While getting text, depending on current value of message’s DataLength property, there may be a  call to .NET Framework’s System.IO.BinaryReader.ReadString method. To read the text, it must first get the encoded length of that text  - this is why method Read7BitEncodedInt is visible on the stack trace. This routine in turn uses ReadByte method which after hitting the end of a stream throws discussed exception.

* Conversion takes place using message's CharacterSet (CCSID) property.