在C / C ++中读取字节方法

时间:2011-09-16 12:10:57

标签: c++ c

我是C的新手,我想知道是否有标准库方法来读取bytes / int / long 例如:getChar(),getInt(),getLong()。

因此,例如,如果我调用getInt(),它将返回4个字节作为字符串并将char指针地址移动4.我在哪里可以找到这些方法?

4 个答案:

答案 0 :(得分:8)

不,库不直接支持二进制(反)序列化。 read()函数将移动流指针,但我不认为您可以绕过与平台相关的代码片段来解释字节流:

std::infile thefile("data.bin", "rb");

float f;
double d;
uint32_t i;

// the following is OK and doesn't constitute type punning
char * const pf = reinterpret_cast<char*>(&f);
char * const pd = reinterpret_cast<char*>(&d);
char * const pi = reinterpret_cast<char*>(&i);

// the following may or may not give you what you expect
// Caveat emptor, and add your own platform-specific code here.
thefile.read(pf, sizeof(float));
thefile.read(pd, sizeof(double));
thefile.read(pi, sizeof(uint32_t));

在仅读取无符号整数值的情况下,您可以执行代数提取,这在某种意义上是类型安全的,只需要您知道序列化数据格式的字节顺序:

unsigned char buf[sizeof(uint32_t)];
thefile.read(reinterpret_cast<char*>(buf), sizeof(uint32_t));

uint32_t n = buf[0] + (buf[1] << 8) + (buf[2] << 16) + (buf[3] << 24); // little-endian

以二进制形式读取浮点数据特别令人厌烦,因为您必须了解有关数据流的大量额外信息:它是否使用IEEE754? (你的平台吗?)enidanness是什么(float endianness与整数字节序无关)?或者它完全代表其他东西?良好的文件格式文档至关重要。


在C中,您将使用fread()和C风格的演员,char * const pf = (char*)(&f)

答案 1 :(得分:1)

我相信你指的是Java的ByteBuffer方法。

请注意,如果您对这些函数处理的相同数据进行操作,那么 Java始终是BIG端,无论主机的本机字节顺序如何。除非您确定不是,否则您的C代码可能正在编译以在 LITTLE endian 计算机上运行。如果您不确定,可以采用一些粗略的指导原则:x86(大多数PC)都是LE。 ARM可以是,但通常是LE。 PowerPC和Itanium是BE。

此外,永远不要将char *void *取消引用任何大于1字节的类型,除非您知道它已正确对齐。如果不是,它将导致总线故障或类似错误。

所以这里将是我的getInt() impl,假设BE /网络字节顺序(例如由Java生成)缓冲区。对于简洁而道歉。

typedef struct ByteBuffer {
    const char * buffer;   /* Buffer base pointer */
    int          nextByte; /* Next byte to parse */
    int          size;     /* Size of buffer */
} ByteBuffer_t;

/* Get int from byte buffer, store results in 'i'. Return 0 on success, -1 on error */
int getInt(ByteBuffer * bb, int * i) {
   const char * b;
   if( (bb->nextByte + 3) < bb->size ) {
      b = &(bb->buffer[bb->nextByte]);
      /* Read as big-endian value */
      *i = (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[0];
      bb->nextByte += 4;
      return 0;
   } else {
      return -1;
   }
}


void test(const char * buf, int bufSize) {
   ByteBuffer_t bb;
   int ival;

   bb.buffer = buf;
   bb.size   = bufSize;
   bb.nextByte = 0;

   while(1) {
      if( 0 == getInt(&bb, &ival) )
          printf("%d\n", ival);
      else
          break;     
   }
}

编辑:删除了ntohl()调用....如果您的源数据真的是大端,则它不属于。如果它在那里调用那么工作,你可能需要在shift-pack上交换字节顺序,这意味着它将解析小端字节流。

答案 2 :(得分:0)

由于指针算法属于C的本质,因此这种类似Java的函数不可用。

要从某个内存缓冲区中获取int,您可以这样做:

/* assuming that buf is of type void * */
int x = *((int *) buf);
/* advance to the position after the end of the int */
((int *) buf)++;

或更紧凑:

int x = *((int *) buf)++;

答案 3 :(得分:0)

有一个getchar()函数。

c中的标准输入法是使用

scanf("<format specifer string>",input param1, param2,...)

查看http://www.cplusplus.com/reference/clibrary/cstdio/scanf/