Skip to content

Character streams with SerialPortStream

MrEngineer02 edited this page May 3, 2017 · 1 revision

Table of Contents

Character Streams

The SerialPortStream object supports both character streams and byte streams simultaneously.

Reading Character Buffers

You can use the method Read(char[], int, int) to use the defined encoding Encoding property to convert bytes in the read buffer to characters. As many characters as possible are read using the Encoding. The Encoding may also read extra bytes and cache them internally if not all characters can be read.

An equivalent method to ReadByte() is also provided, as ReadChar(). The ReadTimeout property defines how long to wait for at least a single character in the read buffer (which may be multiple bytes).

Writing Character Buffers

By using the standard method Write(char[], int, int) you allow for an semi-efficient implementation in writing data. The character stream is first converted to a byte stream and then checked that there is enough bytes in the write buffer before sending them over the serial port. This allows you to know for sure that all the bytes are queued for sending, or none are queued at all.

The term "semi-efficient" is used here, as it's no less efficient than the MS implementation. But an extra copy operation is required (and associated buffers) before the write can complete.

Strings and Things

Reading all Data and Writing a string

You can convert all data in the input read buffer into a string using the ReadExisting() method. This uses the Encoding method. The encoding method will cache bytes that might partially make up a single character, so using this method repeatedly will correctly convert multibyte characters. The conversion process dependent on the Encoding object, and as such there could be side effects when you switch between reading characters and bytes(such as bytes being cached in the Encoding object).

If you want to write a text string, you can do so with the Write(string) method.

Reading and Writing a Line

It's possible to read and write lines of text. The newline character is defined by the property NewLine and by default it is "\n".

To read a single line of text, use the ReadLine() method. This will read all available text, and wait until ReadTimeout for a newline character. If no newline character is in the input stream, a TimeoutException shall be raised.

Conversely, you can write a string of text over the serial port with the WriteLine() method. This is equivalent to the Write(string) method with a newline appended to the end.

Reading up to a String with ReadTo()

Under the hood, the ReadLine() method uses ReadTo() to read all characters in the read buffer until a string sequence is found.

The ReadTo() method is similar to that of the MS implementation, but it ensures accuracy when switching between bytes and characters in error cases. It reads individual bytes from the read buffer until a match is found. In case the match is not found at the end of the string, a TimeoutException is raised.

The MS implementation actually takes the converted characters and converts them back to bytes. This has a subtle side effect, that if you use the MS implementation to ReadTo() which results in a TimeoutException, followed immediately after by a Read(byte[], int, int) call, the data read by Read() may not be the original data received in the serial port, but is dependent on the Encoding on how it read the bytes and then converts them back.

A limitation is placed on the SerialPortStream. The input read buffer is of a fixed size. ReadTo() places an additional limit of 1024 characters on in the input stream. So if the string is not within the first 1024 characters, bytes at the beginning are truncated.

Note: it isn't tested what happens if the read buffer is smaller than the 1024 character buffer that ReadTo() implicitly uses. See ReadTo and ReadBufferSize less than 1024 characters.

Properties

Character Encoding

SerialPortStream supports reading and writing bytes directly, or you can set the Encoding property to an encoding that suits your application. The default encoding is UTF-8. The encoder is used for converting bytes to characters when reading for all Read and Write operations that takes characters or strings.

You should not modify the state of the encoding object after assigning it, this may cause undefined behaviour.

New Line

The property NewLine defines the new line character(s) when you use the functions ReadLine() and WriteLine(). By default it is set to the single character "\n". Some applications may require "\r\n" or simply "\r".

Performance Considerations

Because both byte streams and character streams need to be supported in parallel, some methods can result in suboptimal performance.

In particular, the methods ReadTo(), ReadLine() and ReadChar() need to read byte for byte to look for characters. If you use these methods often and don't need to use byte streams at all, you could get extra performance by using the Read(char[], int, int) methods in your own buffer and searching for the strings yourself.

The reason for this design decision is to accurately support reading byte and character streams simultaneously, which the MS implementation doesn't do properly.