简体   繁体   中英

read from a file to an int buffer in C

I have a txt file with thousands of lines. Length of each line varies. The txt file mainly contains hex data in bytes. For example:

01 01 04 03 = 4 bytes.

Second line might contain 8 bytes, 3rd 40 bytes and so on. There are thousands of such lines.

Now I want to read these bytes into int buffer. I am reading into char buffer and in the memory it saves as 0001 0001 0004 0003, which I do not want and it is considered as 8 Bytes. In memory, it saves as 3031 3031 3034 3030 (ASCII) as it is char buffer. I am converting this to 0001 0001 0004 0003.

Below is my piece of code

FILE *file;

char buffer[100] = { '\0' };
char line[100] = { '0' }; 

if(file!=NULL)
      {
        while(fgets(line, sizeof(line), file)!=NULL)
        {

          for(i = 0; (line[i] != '\r') ; i++)
          {
              buffer[i] = line[i];
          }
        }
       }

I want to read line by line not entire file at once. In the memory I want to see as just 01 01 04 03. I guess using int buffer will help. As soon as it reads the file into buffer line, it is stored as char. Any suggestions please?

I would read in a line, then use strtol to convert the individual numbers in the input. strtol gives you a pointer to the character at which the conversion failed, which you can use as a starting point to find/convert the next number.

You can convert small hex numbers:

#include <ctype.h>
uint8_t digits2hex(char *digits) {
  uint8_t r = 0;
  while (isxdigit(*digits)) {
    r = r * 16 + (*digit - '0');
    digit++;
    /* check size? */
  }
  return r;
}

/* ... */

for(i = 0; (line[i] != '\r') ; i+=2)
{
          hexnumbers[hexcount++] = digits2hex(line + i);
          /* skip white space */
          while (isspace(line[i])) 
            i++
}

You seem to be confusing the textual representation of a byte with the value of the byte (or alternately, expecting your compiler to do more than it does.)

When your program reads in "01", it is reading in two bytes whose values correspond to the ASCII codes for the characters "0" and "1". C doesn't do anything special with them, so you need to convert this sequence into a one-byte value. Note that a C char is one byte and so is the right size to hold this result. This is a coincidence and in any case is not true for Unicode and other wide character encodings.

There are several ways to do this conversion. You can do arithmetic on the bytes yourself like this:

unsigned char charToHex(char c) {
    if (isdigit(c)) return c - '0';
    return 9 + toupper(c) - 'A';
}

...

first = getc(fh);
second = getc(fh);
buffer[*end] = charToHex(first) << 4 | charToHex(second);

(Note that I'm using getc() to read the characters instead of fgets(). I'll go into that later.)

Note also that 'first' is the most significant half-byte of the input.

You can also (re)create a string from the two bytes and call strtol on it:

char buffer[3];
buffer[0] = first;
buffer[1] = second;
buffer[2] = 0;  // null-terminator

buffer[*end] = (char)strtol(buffer, NULL, 16);

Related to this, you'd probably have better luck using getc() to read in the file one character at a time, ignoring anything that isn't a hex digit. That way, you won't get a buffer overflow if an input line is longer than the buffer you pass to fgets(). It also makes it easier to tolerate garbage in the input file.

Here's a complete example of this. It uses isxdigit() to detect hex characters and ignores anything else including single hex digits:

// Given a single hex digit, return its numeric value
unsigned char charToHex(char c) {
    if (isdigit(c)) return c - '0';
    return 9 + toupper(c) - 'A';
}

// Read in file 'fh' and for each pair of hex digits found, append
// the corresponding value to 'buffer'. '*end' is set to the index
// of the last byte written to 'buffer', which is assumed to have enough
// space.
void readBuffer(FILE *fh, unsigned char buffer[], size_t *end) {
    for (;;) {

        // Advance to the next hex digit in the stream.
        int first;
        do {
            first = getc(fh);
            if (first == EOF) return;
        } while (!isxdigit(first));

        int second;
        second = getc(fh);

        // Ignore any single hex digits
        if (!isxdigit(second)) continue;

        // Compute the hex value and append it to the array.
        buffer[*end] = charToHex(first) << 4 | charToHex(second);
        (*end)++;

    }
}
FILE *fp = ...;
int buffer[1024]; /*enough memery*/
int r_pos = 0;/*read start position*/
char line[128];
char tmp[4];
char *cp;
if(fp) {
  while(NULL!=fgets(line, sizeof(line), fp)) {
    cp = line;
    while(sscanf(cp, "%d %d %d %d", &tmp[0], &tmp[1], &tmp[2], &tmp[3])==4) {
      buffer[r_pos++] = *(int *)tmp; /*or ntohl(*(int *)tmp)*/
      cp += strlen("01 01 04 03 ");
    }
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM