Декодирование и переформатирование значений из последовательного массива данных

#c# #windows #forms #visual-studio

#c# #Windows #формы #visual-studio

Вопрос:

Мое приложение получает данные из последовательного интерфейса. Некоторые полученные записи могут отображаться непосредственно в текстовом поле, другие должны быть преобразованы. Одно последовательное сообщение, которое я должен декодировать, содержит 512 байт и несколько сведений.

Для получения данных я использую:

     private void SerialPortDataReceived(object sender, SerialDataReceivedEventArgs e)
    {
        var serialPort = (SerialPort)sender;
        string data = serialPort.ReadExisting();
        dataDecoder(data);         
    }
 

И в декодере данных я делаю следующее:

         private void dataDecoder(string input)
    {
        string post = "";                       //empty string
        char[] buf = input.ToCharArray();       //Converter input String to Char Array

        if (buf[0] == '#')                       //only process records starting with #, others go directly to SetText(string)
        {
            post  = "Decode, Len=";                                      //Informal message   
            int up = int.Parse(buf[2].ToString());                       //Upper byte of 16bit-binary integer
            int low = int.Parse(buf[3].ToString());                      //lower byte of 16bit-binary integer
            int len = low << 8 | up;                                     //converter to decimal int
            post  = len;                                                 //edit string
            post  = " Channel: ";                                        //informal message
            int first = int.Parse(buf[4].ToString());                    //Upper byte of 16bit-binary integer
            int second = int.Parse(buf[5].ToString());                   //lower byte of 16bit-binary integer
            int chnl = second << 8 | first;                              //converter to decimal int
            post  = chnl;                                                //edit string
            post  = "DATA";                                              //informal message


            for (int i = 0; i < 507; i  )                                  //decode contents 6 to 511 (512byte is checsum)
            {
                int k = i   6;                                           //format selector
                int one = int.Parse(buf[k].ToString());                  //Highest byte of 32bit-binary integer
                int two = int.Parse(buf[k   1].ToString());                //second high byte of 32bit-binary integer
                int three = int.Parse(buf[k   2].ToString());            //second low byte of 32bit-binary integer
                int four = int.Parse(buf[k   3].ToString());             //lowest byte of 32bit-binary integer
                int rec = four << 24 | three << 16 | two << 8 | one;     //convert to decimal int
                post  = rec;                                             //edit string                  
                post  = ",";                                             //separation character
            }
            SetText(post);                                               //set text to texbox
        }
        else
        {
            SetText(input);                                              //set input to textbox (unconverted)
        }
    }
}
 

Сборка не сообщает о каких-либо ошибках или предупреждениях. Но когда я запускаю код и он достигает этой функции, программа завершает работу с сообщением

Система.Исключение FormatException: «Входная строка была в неправильном формате».

на линии

 int up = int.Parse(buf[2].ToString());
 

Что я мог бы сделать лучше для решения этой проблемы?

РЕДАКТИРОВАТЬ Вот первые части последовательных данных (взятые из последовательного монитора)

23 42 FC 01 00 00 00 00 00 00 00 00 00 00 00 00

23 — это # 42 — это B, а FC 01 — длина записи, в данном случае известная, и ее 508 (01FC)

Ответ №1:

Я не знаю, какой у вас формат данных, но вы можете использовать регулярное выражение или пользовательское сопоставление, как показано ниже.

 public static unsafe void dataDecoder(string input)
{
    switch (input[0])
    {
        case '#':
            byte[] bytes = Encoding.UTF8.GetBytes(input);
            Map(bytes);
            break;
    }
}

public static unsafe string Map(this byte[] bytes)
{
    
    var offset = 2;
    var post = string.Empty;
    if (bytes == null)
        return post;

    //while (bytes.Length < offset)
    {
        int len =0
        int chnl =0;
        fixed (byte* numPtr = amp;bytes[offset])
        {
            len = *(Int16*)numPtr;
        }
        offset  = 2;
        post  = len;                                                 
        post  = " Channel: ";                                        

        fixed (byte* numPtr = amp;bytes[offset])
        {
            chnl = *(Int16*)numPtr;
        }
        offset  = 2;
        

    }
    // etc...
    return post;

}
 

Комментарии:

1. Что вы подразумеваете под «занимает один символ»? Char может быть 16-битным в C #, а int — 32-битным, поэтому я думаю, что он не может быть больше. Также вы используете string[0] , который я пробовал раньше, но я читал сообщения о том, что это невозможно сделать на C #, потому что string неизменяем.

2. вы можете использовать небезопасный код и считывать данные по указателю, как в примере. Сначала мы пропускаем первый байт ‘#’, второй получаем len Int16

3. это будет ваша длина: фиксированная (byte* numPtr = amp;bytes[2]) { len = (Int16 )numPtr; }

4. Я имел в виду, что Int16 может занимать 2 байта (FF FF), или если хранится в строковом представлении из 5 байт ‘32767’ — в ASCII