【问题标题】:Reading file with POSIX read使用 POSIX 读取文件
【发布时间】:2019-11-03 01:43:55
【问题描述】:

我有一个由以下代码转储的文件:

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 read 函数而不是 fscanf 将值读入 buf

【问题讨论】:

  • 您仍想在buf 中拥有uint_8 值,还是只想读取原始文件?
  • @MarcoBonelli 我想存储 uint8_t 值而不是原始字节。

标签: c posix file-read


【解决方案1】:

嗯...首先让我说使用原始系统调用并不是那么简单。您必须考虑到普通 stdio 函数会在您没有注意到的情况下处理的各种问题和边缘情况。 在编写程序之前仔细阅读the manual page for read

如上所述,您可以通过创建一个简单的映射来实现您想要的,该映射将每个 ASCII 字符映射到其十六进制值。在下面的示例中,我还使用0x0 来填充无效值,但您可以例如将其声明为int8_t 并使用-1 填充无效值。这取决于你。

一旦您有一个将每个 ASCII 字符转换为给定十六进制值的映射,您就可以使用它来简单地查找所需的值,例如 hexmap['a'] == hexmap['A'] == 0xA。您可以通过读取两个十六进制数字然后将它们与简单的左移和二进制 OR 组合来获得单个 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

【讨论】:

    猜你喜欢
    • 2012-10-30
    • 2014-05-18
    • 2015-06-08
    • 1970-01-01
    • 2015-05-28
    • 1970-01-01
    • 2016-11-14
    • 1970-01-01
    • 2020-05-30
    相关资源
    最近更新 更多