Чтение файла с чтением POSIX - PullRequest
       43

Чтение файла с чтением POSIX

2 голосов
/ 03 ноября 2019

У меня есть файл, который выгружается с помощью следующего кода:

for (unsigned long long i = 0; i < 10; i++) {
  unsigned char byte = rand() % 16; 
  printf("%02x", byte);
}

Я могу прочитать этот файл, используя fscanf:

uint8_t *buf;
uint64_t index = 0;
unsigned int byte;
while (fscanf(input_file, "%02x", &byte) == 1) {
  buf[index] = static_cast<uint8_t>(byte);
  index++;
}

Как использовать POSIX *Функция 1008 * вместо fscanf для чтения значений в buf?

1 Ответ

1 голос
/ 03 ноября 2019

Хорошо ... позвольте мне начать с того, что работать с необработанными системными вызовами не так просто. Вы должны принять во внимание множество проблем и крайних случаев, о которых позаботятся обычные функции stdio, даже если вы этого не заметите. Внимательно прочитайте страницу руководства для read перед написанием программы.

С учетом вышесказанного вы можете достичь желаемого, создав простую карту, котораяотображает каждый символ ASCII в его шестнадцатеричное значение. В приведенном ниже примере я использую 0x0, чтобы также заполнить недопустимые значения, но вы можете, например, объявить его как int8_t и заполнить недопустимые значения -1. Это ваше дело.

Как только у вас есть карта, которая переводит каждый символ ASCII в заданное шестнадцатеричное значение, вы можете использовать ее для простого поиска необходимых значений, например, hexmap['a'] == hexmap['A'] == 0xA. Вы можете получить один uint8_t, прочитав две шестнадцатеричные цифры и затем объединив их с простым сдвигом влево и двоичным ИЛИ, например:

uint8_t value = 0xA << 4 | 0x1;
// Using the map:
uint8_t value = hexmap['a'] << 4 | hexmap['1'];
// value == 0xA1

Вот рабочий пример:

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>

static const uint8_t hexmap[128] = {
    0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
    0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
    0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
    0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
    0x0, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
    0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
    0x0, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
    0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
};

int main(void) {
    uint8_t *buf;
    int fd;

    // Open file.

    fd = open("your_file", O_RDONLY);
    if (fd == -1) {
        perror("open failed");
        return 1;
    }

    // Allocate buffer.
    // Make sure it's big enough, or reallocate while reading later.

    buf = malloc(sizeof(uint8_t) * 10);
    if (buf == NULL) {
        perror("malloc failed");
        return 1;
    }

    unsigned char digits[2];
    size_t total = 0;
    ssize_t nread;

    while (1) {
        nread = read(fd, digits, 2);

        if (nread == -1) {
            perror("read failed");
            return 1;
        } else if (nread == 0) {
            // EOF reached
            break;
        }

        buf[total] = hexmap[digits[0]] << 4 | hexmap[digits[1]];
        total++;

        // Here be sure to reallocate buf if total gets too high.
    }

    close(fd);

    // Do whatever you want...
    // For example, print the values.
    for (size_t i = 0; i < total; i++) {
        printf("%d: %hhu\n", i, buf[i]);
    }

    free(buf);

    return 0;
}

Пример ввода:

0a01ff

Выход:

0: 10
1: 1
2: 255
...