#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