开发者

Read bytes methods in C / C++

I am new to C and i was wondering if there are standard library methods to read bytes/int/long such as: getChar(), getInt(), getLong().

So for instance if i call getInt(), it will return the 4 by开发者_Go百科tes as a string and move the char pointer address by 4. Where can i find these methods?


No, binary (de)serialization is not directly supported systematically by the library. The read() function will move the stream pointer along, but I don't think you can get around a platform-dependent piece of code for interpreting the byte stream:

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));

In the case of reading unsigned integral values only, you can perform an algebraic extraction which is in some sense type safe and only requires you to know the endianness of the serialized data format:

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

Reading floating point data in binary is particularly irksome because you have to know quite a lot of extra information about your data stream: Does it use IEEE754? (Does your platform?) What's the enidanness (float endianness is independent from integer endianness)? Or is it represented as something else entirely? Good documentation of the file format is crucial.


In C, you would use fread() and C-style casts, char * const pf = (char*)(&f).


Since pointer arithmetic is in the very nature of C, such Java-like functions are not available there.

To get an int out of some memory buffer you would do:

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

or more compactly:

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


I believe you are referring to Java's ByteBuffer methods.

Note that if you operating on the same data processed by those functions that Java is always BIG endian regardless of the host's native byte order. Unless you know for sure that it's not, your C code is probably compiling to run on a LITTLE endian machine. Some rough guidelines if you're not sure: x86 (most PCs) are LE. ARM can be either, but usually LE. PowerPC and Itanium are BE.

Also, never dereference a char * or void * to any type large than 1-byte unless you know it's properly aligned. It will cause a bus fault or similar error if it's not.

So here would be my getInt() impl, assuming a BE/network byte-order (e.g. produced by Java) buffer. My apologies for being terse.

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;     
   }
}

EDIT: Removed ntohl() call.... it didn't belong if your source data was really big endian. If it worked w/ that call in there, you probably need to swap the byte order on the shift-pack, which means it will be parsing little-endian byte streams instead.


There is a getchar() function.

The standard input methods in c is by using

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

Take a look at http://www.cplusplus.com/reference/clibrary/cstdio/scanf/

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜