System.IO.Ports.SerialPortBase.ReadTo C# (CSharp) Метод

ReadTo() приватный Метод

private ReadTo ( ) : byte[]
Результат byte[]
        protected virtual byte[] ReadTo(params byte[] mark)
        {
            // By using byte[] as a marker instead of char[] or string gives us the advantage of processing "lines" in binary data, however,
            // it definitely limits us to the expanding encondings only. That means, this will not work in the case encoding packs more characters into single byte.
            // We could solve this eg. by params char[] mark override equivalent, but current limitations of decoders (eg. Utf8Decoder class) makes such parsing too complicated nowadays.

            if (mark == null) throw new ArgumentNullException("mark");
            if (mark.Length == 0) throw new ArgumentException("Mark must have non-zero length.");

            if (IsReading)                                     // DataReceived event is being requested so we use internal read buffer rather than the serial port directly
            {
                _readToEvent = new AutoResetEvent(false);      // creates an AutoResetEvent so that the OnDataReceived event handler can signal us that new data are available to check

                Timer readToTimeout = null; bool timedOut = false;
                if (ReadTimeout > 0)
                    readToTimeout = new Timer(delegate { timedOut = true; _readToEvent.Set(); }, null, ReadTimeout, 0);

                while (IsReading)
                {
                    lock (_bufferSync)
                    {
                        int markIndex = BufferIndexOf(mark);                    // look for mark in the received data
                        if (markIndex >= 0)                                     // If found,
                        {
                            byte[] receivedData = GetBufferedData(markIndex);   // read the data up to the mark,
                            AdvancePosition(markIndex + mark.Length);           // and remove them from the buffer.

                            if (readToTimeout != null)
                                readToTimeout.Dispose();                        // We are finished, so cancel the timeout timer, if applicable.

                            return receivedData;
                        }
                    }

                    if (ReadTimeout == 0)                                       // If the user does not want to wait and we don't have a line, return null.
                        return null;

                    _readToEvent.WaitOne();                                     // Wait until the OnDataReceived handler signals us there are new data available to check,
                    // or until the timeout timer signals us.
                    if (timedOut)
                        return null;                                            // If it was the timer, return null.
                }

                // Here we are if the DataReceived event was being requested upon calling this method, but all subscribers has detached before any line marker came in.

                _readToEvent = null;                                            // do some cleaning of stuff we don't need for the direct serial port manipulation
                if (timedOut) return null;
                else
                    if (readToTimeout != null)
                        readToTimeout.Dispose();
            }

            byte[] data = new byte[System.Math.Max(_incomingBufferValidLength, _readBufferSize) + mark.Length];
            int offset = GetBufferedData(data, 0, _incomingBufferValidLength); // read any data which left in the internal read buffer

            int markSearchStart = 0;
            while (true)
            {
                if (offset >= data.Length)                                     // If we have filled the buffer, make a bigger one!
                {                                                              // (the >= is for paranoia reasons, the offset never becomes greater than data.Length in this method)
                    byte[] biggerData = new byte[data.Length * 2];
                    data.CopyTo(biggerData, 0);
                    data = biggerData;
                }

                int read = ReadDirect(data, offset, data.Length - offset);                 // read as much data from serial port as fits in our buffer
                if (read < 1)
                    return null;                                                                        // the operation has timed out

                offset += read;                                                                         // offset now points to where next read should start, or in other words valid length
                int markPos = Array.IndexOf(data, mark[0], markSearchStart, offset - markSearchStart);  // try to find the first byte of mark in the buffer
                if (markPos < 0)
                    markSearchStart = offset;                                                           // we didn't find it, there is no reason to search the whole buffer again next time
                else
                {                                                                                       // okay, we have the first byte
                    if (markPos + mark.Length <= offset)                                                // do we have enough data in the buffer that whole mark could fit in?
                    {
                        int i = 1;
                        for (i = 1; i < mark.Length; i++)                                               // if so, check if the next bytes in buffer match the mark bytes
                            if (data[markPos + i] != mark[i]) break;

                        if (i >= mark.Length)
                        {
                            byte[] finalData = new byte[markPos];                                       // if they do, copy data before marker into the new array
                            Array.Copy(data, 0, finalData, 0, markPos);

                            int remains = offset - markPos - mark.Length;
                            if (remains > 0)                                                            // If we grabbed any data we haven't used,
                                lock (_bufferSync)                                                      // push it to the internal read buffer (we are going to return now).
                                {
                                    if (_incomingBuffer.Length < remains)                               // make enough space if the internal buffer is too small to store remaining data
                                        _incomingBuffer = new byte[remains];                            // We have already read all data that where in the buffer before the while loop,
                                    // so it is okay to lose any current data.
                                    Array.Copy(data, offset - remains, _incomingBuffer, 0, remains);
                                    _incomingBufferPosition = 0;                                        // And so we are storing at the beginning of the circular buffer.
                                    _incomingBufferValidLength = remains;
                                }

                            return finalData;
                        }
                        else                                                                            // If the other bytes do not match the mark bytes, it is not part of the mark,
                            markSearchStart = markPos + 1;                                              // and start the next search at the next position.
                    }
                    else
                        markSearchStart = markPos;                                                      // We don't know if this is marker or not, so try again this position with more data.
                }
            }
        }