我的思路是这样的,先声明个结构体,先用if else判断OCP有效command,然后再判断TAG有效tlv,最后再把里面的val保存到tlv.bin里面,但是不知道怎么代码实现也不知道可不可行,求各位帮忙处理一下,急
读取二进制文件将文件里的数据有效值写入二进制文件
文件是导出的OCP传输协议+TLV数据。
OCP头中送出地址为0x0401,接受地址为0x2C01的是有效command,其余为废command。
ocp头:
列:00 02 00 07 04 01 2C 01 00 02 39 02 00 00 00 00一个OCP头总共16字节
其中00 07为ocp长度指的是后面所有TLV总长度len为7,00为高位07为低位,04 01 2C 01为送出地址和接收地址,此题OCP有用的字节就这几个
ocp头后面跟着TLV
TLV:00 01 03 01 02 01,其中00 01为tag ,03为length, 01 02 01 为value,length代表value长度,有效command中,TAG为0x0028或者TAG为0x0029的是有效TLV,
其余为无效TLV。
将有效command中的有效TLV中的value部分按顺序保存到tlv.bin当中。
文件中文件的字节序。在windows下如果直接读取2字节或者4字节的变量,得到的数字与预期相反。如果需要转换16位字节序,可以用下面的函数。
static inline short change_endain_16(unsigned short usIn)
{
return ((usIn & 0xFF) << 8) | ((usIn & 0xFF00) >> 8);
}
所以是固定16+6字节 有效数据只有3个字节,整个文件都是按这个格式????
typedef struct OCP_
{
USHORT ocp1;
USHORT length;
USHORT sendaddr;
USHORT acceptaddr;
UINT ocp2;
UINT ocp3;
USHORT tag;
BYTE len;
BYTE value[3];
}_ocp;
CString filepath;
CFileDialog dlg(TRUE);
dlg.m_ofn.lpstrFilter = "DAT FILES(*.dat)\0*.dat\0All Files(*.*)\0*.*\0\0";
if (dlg.DoModal() != IDOK)
return;
filepath = dlg.GetPathName();//获取路径名
CFile dataFile;
if (!dataFile.Open(filepath, CFile::modeRead | CFile::typeBinary))
return;
_ocp s_ocp;
long long fileLength = dataFile.GetLength();//文件大小
//保存数据
CString binPath;
binPath = _T("D:\\tlv.bin");
CFile binFile;
if (!binFile.Open(binPath, CFile::modeCreate | CFile::modeWrite | CFile::typeBinary))
return;
while (fileLength > 0)
{
dataFile.Read(&s_ocp, 22);
if (htons(s_ocp.acceptaddr) == 0x2c01 && htons(s_ocp.sendaddr) == 0x0401)
{
if (htons(s_ocp.tag) == 0x0028 || htons(s_ocp.tag) == 0x0029)
{
binFile.Write(s_ocp.value, 3);
}
}
fileLength -= 22;
}
dataFile.Close();
binFile.Close();
TLV的格式编码,解码及示例Demo,可以参考我之前写的这篇博客
https://chexl.blog.csdn.net/article/details/6974201
OPC协议的编码,解码,本质上也是二进制协议,其过程与操作TLV类似
你的需求主要是解析出有效TLV中的Value值,然后将二进制保存到tlv.bin就行了
C语言读取文件数据,操作并保存
https://blog.csdn.net/qq_36488484/article/details/122337902