C 实现二进制文件读写

  利用给出的数据结构:

typedef struct recv_data

 {  

      char    ip[32];

      short   port;               //socket port

      char    buff[PACKET_SIZE];

      short   data_size;

      void    *ptr;

      void    *elm;

         

 } PACKED recv_data_t;

PACKET_SIZE = 4096

1. 首先构造造一个binary文件;

2. 用lua脚本读取这个文件;

3. 解析这个文件。

  本文只涉及第一项任务。

  需要创建一个二进制文件(binary),并对构造的文件内容进行读写,将结构体成员信息数据都写入到二进制文件中并能识别它。

  步骤:1. 利用fopen()函数来打开一个并创建一个二进制文件。

     FILE *fp;      /*FILE 是变量类型,是C中用于文件的标准数结构;声明fp是指向FILE类型的指针*/

     fp = fopen ("wf.dat", "wb");         /*wb参数是只写打开或建立一个二进制文件,只允许写数据;fp是文件指针。*/

心路历程:起初,想利用fgets()函数来从stream所指的文件内读入字符并存到参数s所指的内存空间里,后来发现这样做不可行,会导致程序逻辑上错误,所以改用fwrite 

2. 为了程序的可扩展性,将数据结构修改如下:

typedef struct recv_data

{

uint32_t ip;

uint16_t port;

void *ptr;

 

uint16_t data_size;

char buff[4096];

 

}  recv_data_t;

  以前文件是定长的,现在修改为:buff 最大4096,具体长度由 data_size 确定,于是第一版的代码需要修改。

其中uint32_t表示:uint32_t  unsigned int

uint16_t表示:uint32_t  unsigned short

  在程序中uint32_t、uint16_t都不是标准库的类型,而是扩展数据类型,编译时候会出现未声明错误,需要加上头文件#include <stdint.h>才行

心路历程:(1)我的想法是用malloc函数给data_buff分配内存空间,数据大小由data_size确定,然后将值写入到文件中。那就要为其声明一个指针变量来实现,我定义了一个指针变量p不过这样做貌似画蛇添足。

2)于是我将结构体的成员变量ipbuff修改为*ip*buff,这样就分配了内存空间来将值存入到data.ip中。Buff要求大小是4096,就也用malloc函数分配那么大的内存来存放data_size的内容。

3)后来发现结构体成员变量ip应该是unsigned int的值,而不是指针,于是又把代码修改了下。

3. 由fopen()函数创建并打开二进制文件后,处理过程如下:

(1)使用memset()函数将为结构体分配的内存空间初始化。

(2)由于ip是unsigned int类型的,所以先用sizeof计算ip的大小,再用memcpy()函数将32位ip 地址复制到结构体成员data.ip中。

(3)为端口号赋值。

(4)计算data的大小,data中的内容应该是字符串,所以用strcpy()函数将data_size的内容复制到data.buff中。

(5)由于*ptr和*elm是记录别的数据用的,可以认为是一个KEY,先把他初始化为NULL。

4. 处理完后,利用fwrite()函数将结构体中的数据依次写入到创建的binary文件中。

5. 利用fread()函数,按序将写入binary文件中的数据读出来。

6. 使用winhex工具,验证生成的binary文件,确认其中内容是否与定义的结构一致。

 

源代码如下:

1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <stdint.h>
5
6
7 typedef struct recv_data
8
9 {
10 uint32_t ip;
11
12 uint16_t port;
13
14 void*ptr;
15
16 uint16_t data_size;
17
18 char buff[4096];
19
20 } recv_data_t;
21
22
23 int main (int argc, char**argv)
24
25 {
26 FILE *fp;
27
28 recv_data_t data;
29
30 memset(&data, 0, sizeof(data));
31 uint32_t ip=3232261121u; //192.168.100.1的十进制表示
32 memcpy(&data.ip, &ip,sizeof(uint32_t));
33 data.port =9876;
34 data.data_size=strlen("text message, 1234567890!");
35
36 strcpy(data.buff, "test message, 1234567890!");
37
38 data.data_size = strlen(data.buff);
39
40 data.ptr = NULL;
41
42 fp = fopen ("wf.dat", "wb");
43 if (fp == NULL)
44 {
45 printf ("open file fail\n");
46
47 return-1;
48
49 }
50
51 fwrite (&data.ip,sizeof(data.ip),1,fp);
52 fwrite (&(data.port), sizeof(data.port), 1, fp);
53 fwrite (&(data.data_size), sizeof(data.data_size), 1, fp);
54 fwrite (data.buff, data.data_size, 1, fp);
55
56 fclose(fp);
57
58 fp = fopen("wf.dat","rb");
59
60 fread (&data.ip,sizeof(data.ip),1,fp);
61 printf("%u\n",data.ip);
62
63 fread (&(data.port),sizeof(data.port),1,fp);
64 printf("%d\n",data.port);
65
66 fread (&(data.data_size),sizeof(data.data_size),1,fp);
67 printf("%d\n",data.data_size);
68
69 fread (data.buff,data.data_size,1,fp);
70 printf("%s\n",data.buff);
71
72 fclose(fp);
73
74 return0;
75
76 }
原文地址:https://www.cnblogs.com/kevinji/p/2088500.html