• 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 }
  • 相关阅读:
    LeetCode: Trapping Rain Water
    LeetCode: Text Justification
    LeetCode: Unique Paths
    LeetCode: Unique Binary Search Trees
    向Google、Yahoo!和百度提交Sitemap网站地图
    Paypal IPN&PDT变量列表
    SQL查询和删除重复字段的内容
    [C#]基于.net技术的 Rss 订阅开发
    验证码识别流程
    c# string.Format 格式化日期
  • 原文地址:https://www.cnblogs.com/kevinji/p/2088500.html
Copyright © 2020-2023  润新知