【问题标题】:Read binary data to long int将二进制数据读入 long int
【发布时间】:2018-09-07 13:17:06
【问题描述】:

我需要读取包含一列数字(时间标签)的二进制数据,并使用 8 个字节来记录每个数字。我知道它们是以 little endian 顺序记录的。如果读取正确,它们应该被解码为(示例)

  ...  
  2147426467  
  2147426635  
  2147512936  
  ...

我知道上述数字在 2^31 -1 阈值上。 我尝试读取数据并通过以下方式反转字节序: (length 是字节总数,buffer 是指向包含字节的数组的指针)

unsigned long int tag;
//uint64_t tag;    
for (int j=0; j<length; j=j+8) //read the whole file in 8-byte blocks
   { tag = 0;  
     for (int i=0; i<=7; i++) //read each block ,byte by byte
        {tag ^=  ((unsigned char)buffer[j+i])<<8*i ;} //shift each byte to invert endiandness and add them with ^=
   }
                                                                                              }

运行时,代码给出:

  ...  
  2147426467  
  2147426635  
  18446744071562097256  
  similar big numbers   
  ...

最后一个数字不是(2^64 - 1 - 正确值)。 使用 uint64_t 标签 的结果相同。 代码成功声明标签为

unsigned int tag;

但对于大于 2^32 -1 的标签会失败。至少这是有道理的。
我想我需要在 buffer[i+j] 上进行某种类型的转换,但我不知道该怎么做。

(static_cast<uint64_t>(buffer[j+i])) 

也不行。
我读了a similar question,但仍然需要一些帮助。

【问题讨论】:

  • @jxh 如何将其提升为 unsigned long 而不是 signed int ?
  • buffer的类型是什么?
  • @user2079303 它被声明为 char char *buffer = new char[length];

标签: c++ casting binaryfiles endianness


【解决方案1】:

我们假设buffer[j+i]char,并且chars 在您的平台上签名。转换为 unsigned char 会将 buffer[j+i] 转换为无符号类型。但是,在应用 &lt;&lt; 运算符时,只要 int 可以包含由 unsigned char 表示的所有值,unsigned char 值就会提升为 int

您尝试将 buffer[j+i] 直接转换为 uint64_t 失败,因为如果 char 已签名,则在将值转换为无符号类型之前仍会应用符号扩展。

双重转换可能会起作用(即转换为unsigned char,然后转换为unsigned long),但使用unsigned long 变量来保存中间值应该会使代码的意图更加清晰。对我来说,代码如下所示:

decltype(tag) val = static_cast<unsigned char>(buffer[j+i]);
tag ^= val << 8*i;

【讨论】:

  • 完美运行。谢谢你的解释。我希望我能接受这两个答案。
  • 如果你让buffer包含unsigned char,你可以在分配给val时去掉强制转换。
【解决方案2】:

您使用临时值。 计算机将自动保留存储临时值所需的最少数量。在您的情况下,这将是 32 位。 一旦您将字节移动超过 32 位,它将被转移到遗忘状态。 为了解决这个问题,您需要首先将值显式存储在 64 位整数中。 所以不是

    {tag ^=  ((unsigned char)buffer[j+i])<<8*i ;}

你应该使用这样的东西

    {
       unsigned long long tmp = (unsigned char)buffer[j+i];
       tmp <<= 8*i;
       tag ^=  tmp;
    }

【讨论】:

  • 完美运行。它也适用于unsigned long tmp(至少在我的机器上)
  • long 在所有系统上可能不是 64 位。请参阅stackoverflow.com/questions/6462439/… 了解更多信息。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-10-23
  • 1970-01-01
  • 1970-01-01
  • 2021-07-28
  • 2015-04-20
  • 1970-01-01
相关资源
最近更新 更多