在C语言中从文件读取到int缓冲区
我有一个包含数千行的txt文件。每条线的长度各不相同。txt文件主要包含以字节为单位的十六进制数据。例如: 01 04 03=4个字节 第二行可能包含8个字节,第三行可能包含40个字节,依此类推。有成千上万条这样的线路 现在我想把这些字节读入int缓冲区。我正在读取char缓冲区,它在内存中保存为0001 0001 0004 0003,我不想要它,它被认为是8字节。在内存中,它作为字符缓冲区保存为3031 3031 3034 3030(ASCII)。我正在将其转换为0001 0001 0004 0003 下面是我的一段代码在C语言中从文件读取到int缓冲区,c,C,我有一个包含数千行的txt文件。每条线的长度各不相同。txt文件主要包含以字节为单位的十六进制数据。例如: 01 04 03=4个字节 第二行可能包含8个字节,第三行可能包含40个字节,依此类推。有成千上万条这样的线路 现在我想把这些字节读入int缓冲区。我正在读取char缓冲区,它在内存中保存为0001 0001 0004 0003,我不想要它,它被认为是8字节。在内存中,它作为字符缓冲区保存为3031 3031 3034 3030(ASCII)。我正在将其转换为0001 0001 0004
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];
}
}
}
我想逐行读取,而不是一次读取整个文件。在记忆中我只想看到01 04 03。我想使用int缓冲区会有所帮助。一旦它将文件读入缓冲行,它就被存储为char。有什么建议吗?我会读一行,然后用
strtol
转换输入中的单个数字strtol
为您提供一个指向转换失败的字符的指针,您可以使用该指针作为查找/转换下一个数字的起点。我将读取一行,然后使用strtol
转换输入中的各个数字strtol
为您提供一个指向转换失败的字符的指针,您可以将该指针用作查找/转换下一个数字的起点。您可以转换小的十六进制数:
#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;
}
您可以转换小的十六进制数:
#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;
}
您似乎混淆了字节的文本表示形式和字节的值(或者期望编译器做得更多) 当您的程序读入“01”时,它将读入两个字节,其值对应于字符“0”和“1”的ASCII码。C没有对它们做任何特殊的处理,所以您需要将这个序列转换成一个单字节的值。请注意,C字符是一个字节,因此是保存此结果的正确大小。这是一种巧合,对于Unicode和其他宽字符编码,在任何情况下都是不正确的 有几种方法可以进行这种转换。您可以自己对字节进行如下运算:
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);
与此相关,使用getc()一次读取文件中的一个字符,忽略任何非十六进制数字的内容,可能会更幸运。这样,如果输入行比传递给fgets()的缓冲区长,就不会出现缓冲区溢出。它还可以更容易地容忍输入文件中的垃圾
这里有一个完整的例子。它使用isxdigit()检测十六进制字符,并忽略任何其他内容,包括单个十六进制数字:
// 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)++;
}
}
//给定一个十六进制数字,返回其数值
无符号字符charToHex(字符c){
if(isdigit(c))返回c-'0';
返回9+toupper(c)-‘A’;
}
//读入文件“fh”,并为找到的每对十六进制数字追加
//“缓冲区”的对应值*“结束”设置为索引
//写入“缓冲区”的最后一个字节的
//空间。
void readBuffer(文件*fh,无符号字符缓冲区[],大小*end){
对于(;;){
//前进到流中的下一个十六进制数字。
int优先;
做{
第一个=getc(fh);
if(first==EOF)返回;
}而(!isxdigit(first));
int秒;
秒=getc(fh);
//忽略任何单个十六进制数字
如果(!isxdigit(秒))继续;
//计算十六进制值并将其附加到数组中。
buffer[*end]=charToHex(first)您似乎混淆了字节的文本表示形式与字节的值(或者,期望编译器做得更多)
当您的程序读入“01”时,它将读入两个字节,其值对应于字符“0”和“1”的ASCII码.C对它们没有任何特殊作用,因此您需要将此序列转换为一个字节值。请注意,C字符是一个字节,因此是保存此结果的正确大小。这是一种符合的情况,对于Unicode和其他宽字符编码,在任何情况下都是不符合的
有几种方法可以进行此转换。您可以自己对字节进行如下运算:
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);
与此相关的是,使用getc()一次读取文件中的一个字符,忽略任何非十六进制数字的内容,可能会有更好的运气。这样,如果输入行比传递给fgets()的缓冲区长,就不会出现缓冲区溢出。这也使得更容易容忍输入文件中的垃圾
下面是一个完整的示例。它使用isxdigit()检测十六进制字符,并忽略任何其他内容,包括单个十六进制数字:
// 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)++;
}
}
//给定一个十六进制数字,返回其数值
无符号字符charToHex(字符c){
if(isdigit(c))返回c-'0';
返回9+toupper(c)-‘A’;
}
//读入文件“fh”,并为找到的每对十六进制数字追加
//与“缓冲区”对应的值。“*end”设置为索引
//写入“缓冲区”的最后一个字节的
//空间。
void readBuffer(文件*fh,无符号字符缓冲区[],大小*end){
对于(;;){
//前进到流中的下一个十六进制数字。
int优先;
做{
第一个=getc(fh);
if(first==EOF)返回;
}而(!isxdigit(first));
int秒;
秒=getc(fh);
//忽略任何单个十六进制数字
如果(!isxdigit(秒))继续;
//计算十六进制值并将其附加到数组中。
buffer[*end]=charToHex(first)使用“\r”结束循环时存在两个问题。首先,“\r”(0x0D)通常只出现在Windows上保存的文件中,该文件以“\r\n”结尾。Linux和现代苹果软件使用“\n”(0x0A)只有。如果有任何问题,请忽略“\r”并在“\n”处断开。其次,如果线条长度超过99