当前位置: 首页 > 知识库问答 >
问题:

如何在C语言中从字节数组(用BIG-ENDIAN表示)中提取单个字段

徐景明
2023-03-14

我正试图从byteData中读取几个字节,如下面在我的C代码中所述。byteData中的实际值是一个二进制blob字节数组,采用BIG-ENDIAN字节顺序格式。因此,我不能简单地将字节数组“转换”为字符串。。

byteData字节数组由这三部分组成-

First is `schemaId` which is of two bytes (short datatype in Java)
Second is `lastModifiedDate` which is of eight bytes (long datatype in Java)
Third is the length of actual `byteArray` within `byteData` which we need from `byteData`.
Fourth is the actual value of that `byteArray` in `byteData`.

现在,我正试图从C中的byteData中提取上述特定信息。。。不知何故,我能够提取出schemaId,但得到的值是错误的。。我不知道如何从中提取其他东西。。。

uint16_t schemaId;
uint64_t lastModifiedDate;
uint16_t attributeLength;
const char* actual_binary_value;

while (result.next()) {
    for (size_t i = 0; i < result.column_count(); ++i) {
        cql::cql_byte_t* byteData = NULL;
        cql::cql_int_t size = 0;
        result.get_data(i, &byteData, size);

        if (!flag) {

            // I cannot just "cast" the byte array into a String
            // value = reinterpret_cast<char*>(byteData);

            // now how to retrieve schemaId, lastModifiedDate and actual_binary_value from byteData?

            schemaId = *reinterpret_cast<uint16_t*>(byteData);

            flag = false;
        }
    }

// this prints out 65407 somehow but it should be printing out 32767
    cout<< schemaId <<endl;
}

如果有人需要查看我的java代码,那么这就是我的java代码-

    byte[] avroBinaryValue = text.getBytes();

    long lastModifiedDate = 1289811105109L;
    short schemaId = 32767;

    int size = 2 + 8 + 4 + avroBinaryValue.length; // short is 2 bytes, long 8 and int 4

    ByteBuffer bbuf = ByteBuffer.allocate(size); 
    bbuf.order(ByteOrder.BIG_ENDIAN);

    bbuf.putShort(schemaId);
    bbuf.putLong(lastModifiedDate);
    bbuf.putInt(avroBinaryValue.length);
    bbuf.put(avroBinaryValue);

    // merge everything into one bytearray.
    byte[] bytesToStore = bbuf.array();

            Hex.encodeHexString(bytesToStore)

有谁能帮助我在我的C代码中犯了什么错误,以及为什么我不能正确地从它和其他字段中提取schemaId?

更新:-

用了这个-

schemaId=ntohs(*重新解释

我开始正确获取schemaId的值。

但是现在如何提取其他内容,例如lastModifiedDate,实际byteArray在byteData中的长度,以及该byteArraybyteData`中的实际值。

我在lastModifiedDate中使用了这个,但不知怎的它不起作用--

std::copy(reinterpret_cast<uint8_t*>(byteData + 2), reinterpret_cast<uint8_t*>(byteData + 10), lastModifiedDate);

共有1个答案

陶博赡
2023-03-14

32767是0x7fff。65407是0xff7f。请注意,高阶字节和低阶字节是交换的。您需要交换这些字节以将数字恢复为原始值。幸运的是,有一个名为ntohs(网络到主机简称)的宏或函数正是您想要的。这是宏还是函数,以及在哪个标题中定义,取决于您的系统。但是宏/函数的名称总是ntohs,无论是使用Windows、Linux、Sun还是Mac。

在小型endian机器上,此宏或函数交换形成16位整数的两个字节。在big-endian机器上,这个宏/函数什么都不做(这正是我们想要的)。请注意,现在大多数家用电脑都是little endian。

 类似资料:
  • 问题内容: 在Linux桌面(RHEL4)上,我想从大文件(> 1 Gig)中提取一定范围的字节(通常小于1000)。我知道文件的偏移量和块的大小。 我可以编写代码来执行此操作,但是有命令行解决方案吗? 理想情况是: 问题答案: 尝试:

  • 我有一根绳子, 我想把它转换成一个字节数组。 有人能在这方面引导我吗?我尝试了以下代码,但我得到了ASCII中的数据。我不想那样。

  • 问题内容: 我有一个网页,可以用来上传文件。 现在,我需要检查文件类型是否正确(zip,jpg,pdf,…)。 我可以使用请求随附的mimeType,但我不信任用户,并且说我想确保没有人能够上传在.jpg中重命名的.gif文件。 我认为在这种情况下,我应该检查魔术号码。我发现 这是一个Java库,似乎可以实现“从魔术数字中提取模仿类型”的功能。 这是正确的解决方案还是您建议什么? 更新: 我已经找

  • 我目前有一个Java ByteBuffer,它已经有了Big-Endian格式的数据。然后我想写一个二进制文件作为Little Endian。 下面是刚刚用Big-Endian编写文件的代码: 请注意,byteBuff是一个以Big-Endian格式填充的ByteBuffer。 我最后的办法是使用蛮力方法创建另一个缓冲区,并将ByteBuffer设置为little endian,然后从原始(big

  • 问题内容: 我在数据库中有字节数组。 如何从Java中的字节数组中提取文件扩展名(MIME /类型)? 问题答案: 如果这是为了存储上载的文件: 为文件扩展名创建一列 为浏览器发送的mime类型创建一列 如果您没有原始文件,而只有字节,那么您有两种不错的解决方案。 如果能够使用库,请查看使用mime-util检查字节: http://technopaper.blogspot.com/2009/03

  • 我有一个JavaScript字符串(例如),我只想从中得到。 我试过: 它仍然在警报中返回,我如何让它工作? 它需要适应任何长度数字附加在结束。