用C ++解析缓冲区数据

时间:2012-10-18 12:18:52

标签: c++ parsing buffer

我的C ++项目有一个缓冲区,可以是任何大小,并由蓝牙填充。传入消息的格式类似于0x43 0x0B 0x00 0x06 0xA2 0x03 0x03 0x00 0x01 0x01 0x0A 0x0B 0x0B 0xE6 0x0D,其中以0x43开头,以0x0D结束。因此,这意味着每次填充缓冲区时,根据上述消息格式,它可以具有不同的内容顺序。

static const int BufferSize = 1024;
byte buffer[BufferSize];
  1. 在此缓冲区中解析传入消息的最佳方法是什么?
  2. 由于我来自Java和.NET,将每个提取的消息作为对象的最佳方法是什么?班级可以解决吗?
  3. 我已经创建了一个单独的类来解析缓冲区,就像波纹管一样,我是朝着正确的方向吗?

  4. #include<parsingClass.h>
    class A
    {
       parsingClass ps;
    public:
       parsingClass.parse(buffer, BufferSize);
    }
    

4 个答案:

答案 0 :(得分:2)

class ReturnMessage{
    char *message; 
    public:
    char *getMessage(unsigned char *buffer,int count){
         message = new char[count];
         for(int i = 1; i < count-2; i++){
            message[i-1] = buffer[i];
         }
         message[count-2] = '\0';
         return message;
    }
};
class ParserToMessage{
static int BufferSize = 1024;
unsigned char buffer[BufferSize];
unsigned int counter;
public:
  static char *parse_buffer()
  {
     ReturnMessage rm;
     unsigned char buffByte;
     buffByte = blueToothGetByte(); //fictional getchar() kind of function for bluetooth
     if(buffByte == 0x43){
        buffer[counter++] = buffByte;
        //continue until you find 0x0D
        while((buffByte = blueToothGetByte()) != 0x0D){
            buffer[counter++] = buffByte;
        }
     }
     return rm.getMessage(buffer,counter);
   }
};

答案 1 :(得分:2)

你能将解析器作为'ProtocolUnit'类的方法吗?该方法可以将缓冲区指针/长度作为参数,并返回一个int,指示在正确组装完整协议单元之前从缓冲区消耗的字节数,如果需要更多来自下一个缓冲区的字节,则返回-1。 p>

一旦你有了一个完整的ProtocolUnit,你可以用它做你想做的事情(例如,将它排队到一些处理线程),并为剩余的字节/下一个缓冲区创建一个新的。

答案 2 :(得分:1)

  

我的C ++项目有一个可以是任何大小的缓冲区

我注意到的第一件事是您已经对缓冲区大小进行了硬编码。如果尝试读取大于您在缓冲区中指定的大小的数据,则存在缓冲区溢出的危险。

如果可能,请保持缓冲区大小动态,并根据要接收到缓冲区的数据大小创建字节数组。在创建字节数组之前,请尝试并通知字节数组所在的对象传入缓冲区大小。

int nBufferSize = GetBufferSize();
UCHAR* szByteArray = new UCHAR[nBufferSize];
  

在此缓冲区中解析传入消息的最佳方法是什么?

你是在正确的方面,因为你已经创建并使用了解析器类。我建议使用memcpy一次一个地复制单个数据项,从缓冲区复制到您选择的变量。在这一点上不知道你的意图的更广泛的背景,我不能添加太多。

  

因为我来自Java和.NET,所以最好的方法是什么   每个提取的消息作为对象?班级可以解决吗?

根据您从缓冲区读取的数据的复杂程度以及您的计划,您可以使用类或结构。如果您不需要使用为其他对象提供服务的数据创建对象,则可以使用结构。当你的需求不那么复杂时,结构很棒,因此完整的课程可能有点过分。

  

我已经创建了一个单独的类来解析缓冲区,比如说波纹管,am   我朝着正确的方向前进?

我是这么认为的。

我希望这对初学者有帮助!

答案 3 :(得分:1)

“我应该如何解析这个问题”的问题在很大程度上取决于你想要解析数据的 。您的问题中缺少两件事:

  1. 您是如何收到数据的?你提到蓝牙但是什么是编程媒体?你在读插座吗?你有其他种类的API吗?你是一次收到一个字节还是一个块?
  2. 处理您收到的数据有哪些规则?大多数数据以某种方式或固定字段长度分隔。在你的情况下,你提到它可以是任何长度,但除非你解释如何你要解析它,我无能为力。
  3. 我要提出的一个建议是更改缓冲区的类型以使用std::vector

    std::vector<unsigned char> buffer(normalSize)
    

    您应该选择normalSize为最常见的传入邮件大小。当您将项目推送到其上时,向量将增长,因此,与您创建的数组不同,如果您收到大量消息,则无需担心缓冲区溢出。但是,如果你确实超过了normalSize,那么向量将重新分配足够的内存来应对你的扩展需求。这可能很昂贵,所以你不想经常这样做。

    您使用矢量的方式与数组完全相同。一个关键的区别是你可以简单地将元素推送到向量的末尾,而不是必须保持一个正在运行的指针。因此,假设您一次从蓝牙源收到一个int,您的代码可能如下所示:

    // Clear out the previous contents of the buffer.
    buffer.clear();
    
    int elem(0);
    // Find the start of your message. Throw away elements
    // that we don't need.
    while ( 0x43 != ( elem = getNextBluetoothInt() ) );
    
    // Push elements of the message into the buffer until
    // we hit the end.
    while ( 0x0D != elem )
    {
        buffer.push_back( elem );
    }
    buffer.push_back( elem ); // Remember to add on the last one.
    

    关键的好处是,无论是否推送的字符数是10还是10,000,数组都会自动调整矢量大小而无需执行此操作。