1. 程式人生 > >資料解析

資料解析

對於面向位元組流的協議,如串列埠通訊、TCP,資料解析方法簡介如下(以串列埠為例):
讀取串列埠:

    BYTE readBuf[BUF_SIZE];
	DWORD dwRead;
	DWORD dwWantRead = BUF_SIZE;
	DWORD dwResolveSuccess = 0;
	while (pctcb->bStartCheck)
	{
		dwRead = 0;
		if (ReadFile(hComm, readBuf + dwResolveSuccess, dwWantRead, &dwRead, NULL))
		{
			dwResolveSuccess = ResolveData(readBuf, dwResolveSuccess + dwRead);
			dwWantRead = BUF_SIZE - dwResolveSuccess;
		}
		else
		{
			ShowSystemError(pctcb->hwnd, GetLastError());
			break;
		}
	}

	CloseHandle(hComm);

假設要從中解析出這5路資料:
//PPG和ECG組成一幀
//BYTE ppg_ecg[18] = { 0x40, 0x40, 0x00, 0x00, 0x0A, 0xD1, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0xFF, 0x23, 0x23 };
//BYTE temp1_data[11] = { 0x40, 0x40, 0x00, 0x00, 0x03, 0xD2, 0x01, 0x01, 0xFF, 0x23, 0x23 };
//BYTE temp2_data[11] = { 0x40, 0x40, 0x00, 0x00, 0x03, 0xD3, 0x01, 0x01, 0xFF, 0x23, 0x23 };
//BYTE bo1_data[11] = { 0x40, 0x40, 0x00, 0x00, 0x03, 0xD4, 0x01, 0x01, 0xFF, 0x23, 0x23 };
//BYTE bo2_data[11] = { 0x40, 0x40, 0x00, 0x00, 0x03, 0xD5, 0x01, 0x01, 0xFF, 0x23, 0x23 };
示例程式碼如下:

//資料解析
#define MAX_FRAME_LENGTH 18 //最大幀長
DWORD ResolveData(BYTE* readBuf, DWORD dwLength)
{
	int i, j, head_count, rest_length;
	BYTE checkSum;
	i = head_count = 0;
	while (i < dwLength)
	{
		if (head_count == 2)//遇到了幀頭
		{
			rest_length = dwLength - i;//這是正確的
			if (rest_length >= MAX_FRAME_LENGTH)//最大幀長,這裡是示例幀中的最大幀長,18
			{
				switch (readBuf[i + 3])
				{
				case 0xD1://PPG和ECG資料
					checkSum = 0;
					for (j = i + 3; j < i + 13; j++)
						checkSum += readBuf[j];
					if (checkSum == readBuf[i + 13])
					{
						//解析成功,消費資料...
						i += 16;
						head_count = 0;
					}
					else
					{
						head_count = 1;
						i++;
					}
					break;
				case 0xD2://溫度1
					checkSum = 0;
					for (j = i + 3; j < i + 6; j++)
						checkSum += readBuf[j];
					if (checkSum == readBuf[i + 6])
					{
						//解析成功,消費資料...
						i += 9;
						head_count = 0;
					}
					else
					{
						head_count = 1;
						i++;
					}
					break;
				case 0xD3://溫度2
					checkSum = 0;
					for (j = i + 3; j < i + 6; j++)
						checkSum += readBuf[j];
					if (checkSum == readBuf[i + 6])
					{
						//解析成功,消費資料...
						i += 9;
						head_count = 0;
					}
					else
					{
						head_count = 1;
						i++;
					}
					break;
				case 0xD4://血氧1
					checkSum = 0;
					for (j = i + 3; j < i + 6; j++)
						checkSum += readBuf[j];
					if (checkSum == readBuf[i + 6])
					{
						//解析成功,消費資料...
						i += 9;
						head_count = 0;
					}
					else
					{
						head_count = 1;
						i++;
					}
					break;
				case 0xD5://血氧2
					checkSum = 0;
					for (j = i + 3; j < i + 6; j++)
						checkSum += readBuf[j];
					if (checkSum == readBuf[i + 6])
					{
						//解析成功,消費資料...
						i += 9;
						head_count = 0;
					}
					else
					{
						head_count = 1;
						i++;
					}
					break;
				default:
					head_count = 1;
					i++;
					break;
				}
			}
			else
			{
				//將資料移至陣列的開頭,並改變下次將要讀取的資料量
				memcpy(readBuf, readBuf + i, rest_length);
				return rest_length;
			}
		}
		else
		{
			readBuf[i++] == 0x40 ? head_count++ : head_count = 0;
		}
	}
	return 0;
}