使用C# (Winform)解析DBC文件

本文档提供了一个C# Winform应用程序的示例,演示如何加载和解析DBC文件。程序通过FileLoaderLib库读取DBC文本内容,然后使用DbcLib库的DbcHelper类进行解析,构建DBC文件的结构。解析后的信息在主窗口中以Treeview和Listview展示,方便用户查看节点、消息及信号等详细信息。
摘要由CSDN通过智能技术生成

1 简介

本文以一个demo程序介绍如何使用C# (Winform)解析DBC文件,有关DBC文件的内容,请参考:DBC文件格式文档【翻译】

 

2 程序结构

程序结构

 

解决方案

 

3 加载DBC

在本demo程序中,使用了一个dll库加载DBC文件,这个库为FileLoaderLib,是对C#自带类FileStream和StreamReader的简单封装,只有一个Load函数,用来将文本中的所有内容读入字符串待用。

        /// <summary>
        /// 加载文本文件到字符串
        /// </summary>
        /// <param name="path">文件路径</param>
        /// <param name="stringOut">输出的字符串</param>
        /// <returns></returns>
        public static int Load(string path, ref string stringOut)
        {
            FileStream fs = null;
            StreamReader sr = null;

            try
            {
                fs = new FileStream(path, FileMode.Open, FileAccess.Read);
                sr = new StreamReader(fs);

                stringOut = sr.ReadToEnd();
            }
            catch (Exception en)
            {
                if (sr != null)
                {
                    sr.Close();
                }
                if (fs != null)
                {
                    fs.Close();
                }
                return ExceptionHandler.Report("加载文件失败" + en.Message);
            }

            if (sr != null)
            {
                sr.Close();
            }
            if (fs != null)
            {
                fs.Close();
            }

            return 0;
        }

4 解析

解析过程在DbcLib库的DbcHelper类中的Parse函数中实现,首先调用FileLoader.Load将DBC读到fileBuffer,然后调用StrToDbeFile函数将fileBuffer解析到dbcFile,dbcFile是用来描述DBC的类,其中定义了消息、信号等内容,注意本程序只解析了常用部分,如果你用到剩余部分,可以自行修改,稍后我会上传完整工程。

        public int Parse(string _path)
        {
            int err = 0;

            path = _path;

            err = FileLoader.Load(path, ref fileBuffer);

            err = StrToDbeFile();

            return err;
        }
        private int StrToDbeFile()
        {
            int err = 0;
            string[] bufferAry = null;
            dbcFile = new DbcFile();

            if (fileBuffer == null)
            {
                if (fileBuffer == "")
                {
                    ExceptionHandler.Report("Dbc文件为空");
                }
            }

            bufferAry = fileBuffer.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
            if (bufferAry.Length < 3)
            {
                return ExceptionHandler.Report("Dbc文件格式错误");
            }

            int lineNum = bufferAry.Length;
            bool isMessageValid = false;

            for (int i = 0; i < lineNum; i++)
            {
                string[] lineAry = bufferAry[i].Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
                if (lineAry.Length < 1)
                {
                    return ExceptionHandler.Report("Dbc文件行格式错误");
                }
                switch (lineAry[0])
                {
                    case "VAL_:":
                        {
                 
                            break;
                        }
                    case "CM_:":
                        {
                            Comment cmt = new Comment();
                            cmt.comment = bufferAry[i];
                            dbcFile.comments.Add(cmt);
                            break;
                        }
                    case "BU_:":
                        {
                            for (int j = 1; j < (lineAry.Length); j++)
                            {
                                dbcFile.nodes.Add(lineAry[j]);
                            }
                            break;
                        }
                    case "BO_":
                        {
                            Message message = new Message();
                            uint id = Convert.ToUInt32(lineAry[1]);
                            //跳过默认的消息
                            if (id == 0xC0000000)
                            {
                                isMessageValid = false;
                                break;
                            }
                            else
                            {
                                isMessageValid = true;
                            }
                            //最高位为1的为扩展帧
                            if ((id & 0x80000000) != 0)
                            {
                                id &= 0x7FFFFFFF;
                                message.isExternId = true;
                            }
                            else
                            {
                                message.isExternId = false;
                            }
                            message.messgeId = id;
                            message.messageName = lineAry[2].Substring(0, lineAry[2].Length - 1);
                            message.messageSize = Convert.ToUInt32(lineAry[3]);
                            message.transmitter = lineAry[4];

                            dbcFile.messages.Add(message);
                            break;
                        }
                    case "SG_":
                        {
                            if (isMessageValid)
                            {
                                uint byteOffset = 0;
                                Signal signal = new Signal();
          
                                signal.signalName = lineAry[1];
                                if (lineAry[2] == ":")
                                {
                                    signal.multiplexerIndicator = -2;
                                    byteOffset = 0;
                                }
                                else
                                {
                                    byteOffset = 1;
                                    if (lineAry[2][0] == 'M')
                                    {
                                        signal.multiplexerIndicator = -1;
                                    }
                                    else if (lineAry[2][0] == 'm')
                                    {
                                        signal.multiplexerIndicator = Convert.ToInt32(lineAry[2].Substring(1, lineAry[2].Length - 1));
                                    }
                                    else
                                    {
                                        return ExceptionHandler.Report("Dbc信号格式错误");
                                    }
                                }

                                string[] sp = lineAry[3 + byteOffset].Split(new char[] { '|', '@' }, StringSplitOptions.RemoveEmptyEntries);

                                signal.startBit = Convert.ToUInt32(sp[0]);
                                signal.signalSize = Convert.ToUInt32(sp[1]);
                                if (sp[2][0] == '0')
                                {
                                    signal.byteOrder = 0;
                                }
                                else if (sp[2][0] == '1')
                                {
                                    signal.byteOrder = 1;
                                }
                                if (sp[2][1] == '+')
                                {
                                    signal.valueType = 0;
                                }
                                else if (sp[2][1] == '-')
                                {
                                    signal.valueType = 1;
                                }

                                string[] sp1 = lineAry[4 + byteOffset].Split(new char[] { '(', ',', ')' }, StringSplitOptions.RemoveEmptyEntries);
                                signal.factor = Convert.ToDouble(sp1[0]);
                                signal.offset = Convert.ToDouble(sp1[1]);

                                string[] sp2 = lineAry[5 + byteOffset].Split(new char[] { '[', '|', ']' }, StringSplitOptions.RemoveEmptyEntries);
                                signal.minimum = Convert.ToDouble(sp2[0]);
                                signal.maximum = Convert.ToDouble(sp2[1]);

                                signal.uintStr = lineAry[6 + byteOffset];

                                signal.receivers = lineAry[7 + byteOffset].Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);

                                dbcFile.messages[dbcFile.messages.Count - 1].signals.Add(signal);
                            }
                            break;
                        }
                }
            }
            return err;
        }

5 显示

显示部分在主窗体MainWid类中实现,左边用了一个Treeview显示DBC中的节点和消息列表,右侧用Listview选中的消息中的信号列表,这两个控件放在splitContainer控件中,布局如下图:

 

当点击浏览按钮选择要解析的DBC文件后,会执行dbcHelper.Parse函数,完成DBC解析,然后调用UpdateDbcTreeview函数将节点、消息列表加载到左侧Treeview中。

        private void UpdateDbcTreeview()
        {
            for (int i = 0; i < treeView1.Nodes.Count; i++)
            {
                treeView1.Nodes[i].Nodes.Clear();
            }

            for (int i = 0; i < dbcHelper.dbcFile.nodes.Count; i++)
            {
                treeView1.Nodes[0].Nodes.Add(dbcHelper.dbcFile.nodes[i]);
            }
            for (int i = 0; i < dbcHelper.dbcFile.messages.Count; i++)
            {
                treeView1.Nodes[1].Nodes.Add(dbcHelper.dbcFile.messages[i].messageName);
            }

            treeView1.ExpandAll();
        }

鼠标点击想要查看的消息名,触发Treeview的AfterSelect事件,在事件中调用UpdateDbcListview函数,将信号列表显示在ListView中

        private void UpdateDbcListview(int index)
        {
            ListViewItem item;
            listView1.BeginUpdate();
            listView1.Items.Clear();

            for (int i = 0; i < dbcHelper.dbcFile.messages[index].signals.Count; i++)
            {
                item = new ListViewItem();
                item.Text = dbcHelper.dbcFile.messages[index].signals[i].signalName;
                item.SubItems.Add(dbcHelper.dbcFile.messages[index].signals[i].startBit.ToString());
                item.SubItems.Add(dbcHelper.dbcFile.messages[index].signals[i].signalSize.ToString());
                item.SubItems.Add(ByteOrder[dbcHelper.dbcFile.messages[index].signals[i].byteOrder]);
                item.SubItems.Add(ValueType[dbcHelper.dbcFile.messages[index].signals[i].valueType]);
                item.SubItems.Add(dbcHelper.dbcFile.messages[index].signals[i].factor.ToString());
                item.SubItems.Add(dbcHelper.dbcFile.messages[index].signals[i].offset.ToString());
                item.SubItems.Add(dbcHelper.dbcFile.messages[index].signals[i].minimum.ToString());
                item.SubItems.Add(dbcHelper.dbcFile.messages[index].signals[i].maximum.ToString());
                item.SubItems.Add(dbcHelper.dbcFile.messages[index].signals[i].uintStr);
                listView1.Items.Add(item);
            }
            listView1.EndUpdate();
        }

效果如下图:

 

这就是DBC文件解析demo的所有内容了,具体的应用大家可以自由发挥,有问题可以留言交流。

  • 20
    点赞
  • 63
    收藏
    觉得还不错? 一键收藏
  • 11
    评论
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值