使用 POSIX 读取文件
Reading file with POSIX read
我有一个由以下代码转储的文件:
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
?
好吧...让我先说使用原始系统调用并不是那么简单。您必须考虑正常 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
我有一个由以下代码转储的文件:
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
?
好吧...让我先说使用原始系统调用并不是那么简单。您必须考虑正常 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