gpt4 book ai didi

c - 用C读取二进制文件

转载 作者:太空宇宙 更新时间:2023-11-04 01:02:18 25 4
gpt4 key购买 nike

当前正在尝试用C编写程序以读取.bin文件。你可以从我的代码中看到,我显然漏掉了一些东西,我试着读了很多,但仍然完全被卡住了正如所料,我的输出不是有意的我期望的输出示例是
YV2840 KCLT KDAB 2014年1月16日星期四12:44:00
当我试图阅读一个关于航空公司航班的.bin文件时。我认为这可能是错误的原因如下。
我应该定义一个名为“人类可读日期字符串”的结构当然,这是不可能的,因为它将生成一个编译器错误也许我不应该照字面意思来理解它,因为现在我把它定义为“时间戳”。
顺序和大小与写入文件的格式不匹配。
这是bin文件,如果有人感兴趣的话:http://www.filedropper.com/acars
这是我的代码:

#include <stdio.h>
#include <stdlib.h>

typedef struct MyStruct_struct {
int FlightNum[7];
char OriginAirportCode[5];
char DestAirportCode[5];
int TimeStamp;
} MyStruct;

int main() {
FILE * bin;
MyStruct myStruct;
bin = fopen("acars.bin", "rb");

while(1) {
fread(&myStruct,sizeof(MyStruct),1,bin);
if(feof(bin)!=0)
break;
printf("%d",myStruct.FlightNum);
printf("%s" ,myStruct.OriginAirportCode);
printf("%s" ,myStruct.DestAirportCode);
printf("%d", myStruct.TimeStamp);
}

fclose(bin);
return 0;
}

最佳答案

如果要将二进制数据读入程序,则需要查看要读取的内容hexdumpod是查看数据的好工具:

$ hexdump -C -n 512 dat/acars.bin
00000000 59 56 32 38 32 37 00 4b 43 4c 54 00 4b 53 52 51 |YV2827.KCLT.KSRQ|
00000010 00 00 00 00 2c 83 d0 52 59 56 32 37 38 32 00 4b |....,..RYV2782.K|
00000020 43 4c 54 00 4b 53 52 51 00 00 00 00 cc 3e ed 52 |CLT.KSRQ.....>.R|
00000030 59 56 32 37 33 32 00 4b 43 4c 54 00 4b 53 52 51 |YV2732.KCLT.KSRQ|
00000040 00 00 00 00 88 f4 d5 52 59 56 32 36 37 35 00 4b |.......RYV2675.K|
00000050 43 4c 54 00 4b 53 52 51 00 00 00 00 20 57 9f 52 |CLT.KSRQ.... W.R|
00000060 59 34 39 38 34 31 00 4b 4d 43 4f 00 4d 4d 4d 58 |Y49841.KMCO.MMMX|

根据您的描述,您有航班号、出发机场、目的地机场和时间戳。查看数据,您会发现一个航班号 YV2827(以空结尾),您有 KCLT,它是夏洛特/道格拉斯国际机场的IACO标识符,下一个 KSRQ(佛罗里达萨拉索塔机场的IACO标识符),后面是几个字节的填充,最后是一个4字节的数字,表示时间戳所以数据文件是有意义的。
现在怎么读呢?如果您的描述有效,那么包含元素的结构应该提供读取数据的方法。您可能需要使用不同的成员和不同的属性才能计算出填充,但是应该可以使用以下内容:
typedef struct {
char flight[7];
char dept[5];
char dest[5];
unsigned tstamp;
} flight;

接下来,如何读取文件,并将值存储在代码的内存中。如果不需要存储这些值,那么只需简单地读取和打印数据即可假设您需要存储它以实际使用数据,那么在不知道 acars.bin中包含多少航班的情况下,您将需要一个读取/分配内存以保存数据的方案。
一种灵活的方法是使用静态缓冲区读取每个航班,然后使用 malloccalloc分配一组指向飞行的指针,以及必要时保留cc>保持飞行数据。类似于:
    flight buf = {{0}, {0}, {0}, 0};
flight **flts = NULL;
size_t idx = 0;
size_t nbytes = 0;
...
/* allocate MAXS pointers to flight */
flts = xcalloc (MAXS, sizeof *flts);

/* read into buf until no data read, allocate/copy to flts[i] */
while ((nbytes = fread (&buf, sizeof buf, 1, fp))) {
flts[idx] = calloc (1, sizeof **flts);
memcpy (flts[idx++], &buf, sizeof **flts);

if (idx == maxs) /* if pointer limit reached, realloc */
flts = (flight **)xrealloc_dp((void *)flts, &maxs);
}

上面的代码为flts中的flight分配了初始数量的指针,并使用静态结构 realloc作为缓冲区从acars.bin文件读取数据。在读取 buf且非零的读取中,内存被分配用于存储 nbytes中的缓冲区,并使用 flts[idx]将数据从 memcpy复制到 buf。(您应该添加验证,确认所读内容实际上是您所期望的内容)。
使用一个标准的重新分配方案,当达到这个数字时,首先将 flts[idx]指针分配给struct,指针的数量通过 maxs被重新分配到当前数量的两倍(对于双指针宏,这是一个简单的重新分配——您也可以使用一个简单的函数)这里的目的只是保持代码主体的干净,这样逻辑就不会被所有的 xrealloc_dp验证代码等所掩盖。。
在完全读取acars.bin之后,您将所有值存储在 realloc中(注意,时间戳存储为 flts值,因此转换为日历时间类型并格式化输出将留给您的输出例程)。输出的简单重新格式化可以是:
    for (i = 0; i < 10; i++) {
time_t fdate = (time_t)flts[i]->tstamp;
printf (" flight[%4zu] %-8s %-5s %-5s %s", i, flts[i]->flight,
flts[i]->dept, flts[i]->dest, ctime (&fdate));
}

其中 unsigned int被转换为 flts[i]->tstamp,然后与 time_t一起使用,以提供格式化的输出日期以及其他飞行数据。
把所有的部分放在一起,理解 ctimexcalloc只是 xrealloc_dpcalloc的简单错误检查宏,您可以使用如下内容 realloc中包含 2778个航班,下面的代码只打印前10个和后10个航班的数据:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

/* calloc with error check - exits on any allocation error */
#define xcalloc(nmemb, size) \
({ void *memptr = calloc((size_t)nmemb, (size_t)size); \
if (!memptr) { \
fprintf(stderr, "error: virtual memory exhausted.\n"); \
exit(EXIT_FAILURE); \
} \
memptr; \
})

/* realloc with error check - exits on any allocation error */
#define xrealloc_dp(ptr,nmemb) \
({ \
void **p = ptr; \
size_t *n = nmemb; \
void *tmp = realloc (p, 2 * *n * sizeof tmp); \
if (!tmp) { \
fprintf (stderr, "%s() error: virtual memory exhausted.\n", __func__); \
exit (EXIT_FAILURE); \
} \
p = tmp; \
memset (p + *n, 0, *n * sizeof tmp); /* set new pointers NULL */ \
*n *= 2; \
p; \
})

#define MAXS 256

typedef struct {
char flight[7];
char dept[5];
char dest[5];
unsigned tstamp;
} flight;

int main (int argc, char **argv) {

flight buf = {{0}, {0}, {0}, 0};
flight **flts = NULL;
size_t idx = 0;
size_t nbytes = 0;
size_t maxs = MAXS;
size_t i, index;
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;

if (!fp) {
fprintf (stderr, "error: file open failed '%s'.\n", argv[1]);
return 1;
}

/* allocate MAXS pointers to flight */
flts = xcalloc (MAXS, sizeof *flts);

/* read into buf until no data read, allocate/copy to flts[i] */
while ((nbytes = fread (&buf, sizeof buf, 1, fp))) {
flts[idx] = calloc (1, sizeof **flts);
memcpy (flts[idx++], &buf, sizeof **flts);

if (idx == maxs) /* if pointer limit reached, realloc */
flts = (flight **)xrealloc_dp((void *)flts, &maxs);
}
if (fp != stdin) fclose (fp);

printf ("\n There are '%zu' flights in acars data.\n", idx);

printf ("\n The first 10 flights are:\n\n");
for (i = 0; i < 10; i++) {
time_t fdate = (time_t)flts[i]->tstamp;
printf (" flight[%4zu] %-8s %-5s %-5s %s", i, flts[i]->flight,
flts[i]->dept, flts[i]->dest, ctime (&fdate));
}

printf ("\n The last 10 flights are:\n\n");
index = idx - 10;
for (i = index; i < idx; i++) {
time_t fdate = (time_t)flts[i]->tstamp;
printf (" flight[%4zu] %-8s %-5s %-5s %s", i, flts[i]->flight,
flts[i]->dept, flts[i]->dest, ctime (&fdate));
}

/* free memory */
for (i = 0; i < idx; i++)
free (flts[i]);
free (flts);

return 0;
}

输出
$ ./bin/readacars dat/acars.bin

There are '2778' flights in acars data.

The first 10 flights are:

flight[ 0] YV2827 KCLT KSRQ Fri Jan 10 17:33:00 2014
flight[ 1] YV2782 KCLT KSRQ Sat Feb 1 12:37:00 2014
flight[ 2] YV2732 KCLT KSRQ Tue Jan 14 20:38:00 2014
flight[ 3] YV2675 KCLT KSRQ Wed Dec 4 10:24:00 2013
flight[ 4] Y49841 KMCO MMMX Tue Jul 23 13:25:00 2013
flight[ 5] Y45981 KMCO MMMX Wed Feb 26 13:31:00 2014
flight[ 6] Y45980 MMMX KMCO Tue Mar 25 13:49:00 2014
flight[ 7] Y40981 KMCO MMMX Wed Mar 5 13:23:00 2014
flight[ 8] Y40980 MMMX KMCO Sat Mar 29 11:38:00 2014
flight[ 9] XX0671 KJFK MSLP Tue Mar 25 05:46:00 2014

The last 10 flights are:

flight[2768] 4O2993 KJFK MMMX Wed Feb 12 09:25:00 2014
flight[2769] 1L9221 KSAT KSFB Thu Jan 9 15:41:00 2014
flight[2770] 1L1761 KCID KSFB Tue Jan 14 13:11:00 2014
flight[2771] 1L1625 KABE KSFB Thu Jan 16 10:22:00 2014
flight[2772] 1L0751 KMFE KSFB Thu Jan 16 19:52:00 2014
flight[2773] 1L0697 KTYS KSFB Wed Jan 15 10:21:00 2014
flight[2774] 1L0696 KSFB KTYS Wed Jan 15 07:00:00 2014
flight[2775] 1L0655 KIAG KSFB Fri Jan 17 21:11:00 2014
flight[2776] 1L0654 KSFB KIAG Fri Jan 17 15:49:00 2014
flight[2777] 1L0641 KGFK KSFB Fri Jan 17 14:21:00 2014

存储器错误/泄漏检查
在任何动态分配内存的代码中,都必须使用内存错误检查程序来确保没有写超出分配内存的内容,并确认已释放了分配的所有内存对于Linux acars.bin是正常的选择有这么多微妙的方法来滥用一块内存,可能会导致真正的问题,没有理由不这样做每个平台都有类似的内存检查程序。它们使用起来很简单。把你的程序运行一遍。
$ valgrind ./bin/readacars dat/acars.bin
==12304== Memcheck, a memory error detector
==12304== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
==12304== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==12304== Command: ./bin/readacars dat/acars.bin
==12304==

There are '2778' flights in acars data.

The first 10 flights are:

flight[ 0] YV2827 KCLT KSRQ Fri Jan 10 17:33:00 2014
flight[ 1] YV2782 KCLT KSRQ Sat Feb 1 12:37:00 2014
flight[ 2] YV2732 KCLT KSRQ Tue Jan 14 20:38:00 2014
<snip>
flight[2776] 1L0654 KSFB KIAG Fri Jan 17 15:49:00 2014
flight[2777] 1L0641 KGFK KSFB Fri Jan 17 14:21:00 2014
==12304==
==12304== HEAP SUMMARY:
==12304== in use at exit: 0 bytes in 0 blocks
==12304== total heap usage: 2,812 allocs, 2,812 frees, 134,011 bytes allocated
==12304==
==12304== All heap blocks were freed -- no leaks are possible
==12304==
==12304== For counts of detected and suppressed errors, rerun with: -v
==12304== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2)

valgrind已分配的字节数和所有堆块都已释放--不可能有任何泄漏确认您正在释放所有分配的内存。错误摘要:来自0上下文的0个错误确认在分配的内存块之外没有意外写入。
看看代码,如果您有任何问题,请告诉我,我很乐意提供进一步的帮助。

关于c - 用C读取二进制文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33716050/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com