C语言 结构体数组保存到二进制文件中

时间:2023-01-04 08:54:43
在项目中我定义了一个结构体数组,头文件如下:

#ifndef MY_TABLE_STRUCT_H
#define  MY_TABLE_STRUCT_H

#define  POLICY_UTIL_ARRAY_LENGTH   256*64

#define  ARRAY_SIZE 256

long saved_policy_id[10];
long saved_udp_allow_IP_ID[10];
long save_log_ID[10];


/*与日志审计相关的文件路径定义*/

#define SYSTEM_LOG   "/tmp/log/system.log"
#define HTTP_LOG   "/tmp/log/http.log"
#define SMTP_LOG   "/tmp/log/smtp.log"
#define POP3_LOG   "/tmp/log/pop3.log"

#define SYSTEM_INTERMEDIARY_LOG   "/tmp/log/system_intermediary.log"
#define HTTP_INTERMEDIARY_LOG  "/tmp/log/http_intermediary.log"
#define SMTP_INTERMEDIARY_LOG  "/tmp/log/smtp_intermediary.log"
#define POP3_INTERMEDIARY_LOG  "/tmp/log/pop3_intermediary.log"


typedef struct{
int used; //0 for unused
int AppID; 
/*
       00 "系统",
       01 "HTTP应用",
02 "SMTP应用",
03 "POP3应用",
04 "FTP应用",
05 "TELNET应用",
06 "NULL ",
07 "用户自定义应用",
08 "TCP空白协议",
09 "UDP应用",
0a "ORACLE数据库应用",
0b "SQL Server 数据库应用",
0c "邮件服务器与邮件服务器应用",
*/
char SourceIP[20];
short SourcePort;
char DestIP[20];
short DestPort;
char SourceType; //I for inner;O for outter
char IsDestProxyMode;
short MaxConn;
char IsWorking; 
            // 'Y' for "自动启用,现启用"
            //'N' for "自动启用,现停用"
            //'U' for "手动启用,现停用"
            //'W' for "手动启用,现启用"
       char IsAuth;
// 0 for no auth
// 1  for auth
char name[20];

UINT16 InnerPort; //for udp
UINT16 OuterPort;

char IsAllowed; //安全策略黑白指示
              // 'Y' for 白
              // 'N' for 黑
        char FromTime[8][8];
 char ToTime[8][8];
 char WeekDay[8][8];


 //for udp allowed ip
 unsigned int inner_udp_ip[256];
 unsigned int outer_udp_ip[256];

 //for tcp allowed ip
 struct IP {
  char ip[255];
  int    black_white;
  } allowed_ip[256];
  
 struct POLICY {
long p_id;
  short type;
char IsWorking;
char p_content[255];
char IsAllowed;
  } policy[64];  
}TABLE_CHANNEL;

TABLE_CHANNEL table_channels[ARRAY_SIZE];

#endif

将结构体数组中的数据保存到文件中,实现函数如下:

void chn_write_file()
{
   FILE *fp;
int i;

DO_LOG("chn_write_file():write to the file start...\n");

fp=fopen("/tmp/data/db_file/tcp_file","wb");
if(fp==NULL)
{
printf("file /tmp/udp_chn open error\n");
return;
}
//for(i=0;i<256;i++)
//fwrite(&table_channels[i],sizeof(TABLE_CHANNEL),1,fp);//把内存中的信息写入到文件中去

fwrite(table_channels, sizeof(TABLE_CHANNEL), 256, fp);

fclose(fp);

DO_LOG("chn_write_file():write to the file end...\n");
}


从文件中读取数据存储到结构体数组中,实现函数如下:

void chn_read_file()
{
MY_DEBUG_LOG("chn_read_file():read from the file start...\n");
DO_LOG("chn_read_file():read from the file start...\n");

FILE *fp;
int i, j;

fp= fopen("/tmp/data/db_file/tcp_file", "rb");

if(fp == NULL)
{
DO_LOG("chn_read_file():open file failed, because:%s!\n", strerror(errno));

return ;
}

/*for(i = 0; i< 256; i++)
{
fread(&table_channels[i], sizeof(TABLE_CHANNEL), 1, fp);
}*/

fread(table_channels, sizeof(TABLE_CHANNEL), 256, fp);
        /*****打印结构体数组中的数据*******/
MY_DEBUG_LOG("chn_read_file(): The informations of approuteways bellows:\n");

    for(i =0; i<256; i++)
{
if(table_channels[i].used == 0)
  {
continue;
}

MY_DEBUG_LOG("[ReadFile]:ID:%d, used:%d, AppID:%d, SourceIP:%s, SourcePort:%d,\
DestIP:%s, DestPort:%d, SourceType:%c, IsDestProxyMode:%c, MaxConn:%d,\
IsWorking:%c, IsAuth:%c, InnerPort:%d, OuterPort:%d, IsAllowed:%c, name:%s!\n", \
i, table_channels[i].used, table_channels[i].AppID,table_channels[i].SourceIP,table_channels[i].SourcePort, \
table_channels[i].DestIP, table_channels[i].DestPort,  table_channels[i].SourceType, table_channels[i].IsDestProxyMode,\
table_channels[i].MaxConn,  table_channels[i].IsWorking,table_channels[i].IsAuth,table_channels[i].InnerPort,\
table_channels[i].OuterPort,table_channels[i].IsAllowed,table_channels[i].name);
}

MY_DEBUG_LOG("chn_read_file(): The informations of allowd time bellows:\n");

 for(i=0; i<256; i++)
 {

if(table_channels[i].used == 0)
  {
continue;
}

for(j=0; j<8; j++)
{
if(table_channels[i].FromTime[j][0] == 0)
{
continue;
}

if(table_channels[i].ToTime[j][0] == 0)
{
continue;
}

if(table_channels[i].WeekDay[j][0] == 0)
{
continue;
}


MY_DEBUG_LOG("chn_read_file():ID:%d,FormTime:%s,ToTime:%s,WeekDay:%s\n",\
i,&table_channels[i].FromTime[j][0], &table_channels[i].ToTime[j][0], &table_channels[i].WeekDay[j][0]);
}

 }

 MY_DEBUG_LOG("chn_read_file(): The informations of allowd IPs bellows:\n");

 for(i=0; i<256; i++)
 {

if(table_channels[i].used == 0)
  {
continue;
}

for(j=0; j<256; j++)
{
if(table_channels[i].allowed_ip[j].ip[0] ==0)
{
continue;
}


if(table_channels[i].allowed_ip[j].black_white == 0)
{
MY_DEBUG_LOG("chn_read_file():ID:%d, ip %s, black_white:%d\n", 
i, table_channels[i].allowed_ip[j].ip, table_channels[i].allowed_ip[j].black_white);
}
}

 
 }


       MY_DEBUG_LOG("chn_read_file(): The informations of allowd users bellows:\n");
for(i=0; i<256; i++)
 {

if(table_channels[i].used == 0)
  {
continue;
}

for(j=0; j<256; j++)
{
if(table_channels[i].allowed_ip[j].ip[0] ==0)
{
continue;
}


if(table_channels[i].allowed_ip[j].black_white == 1)
{
MY_DEBUG_LOG("chn_read_file():ID:%d, users %s, black_white:%d\n", 
i, table_channels[i].allowed_ip[j].ip, table_channels[i].allowed_ip[j].black_white);
}
}

 
 }

MY_DEBUG_LOG("chn_read_file(): The informations of policies bellows:\n");

for(i=0; i<256; i++)
 {
  if(table_channels[i].used == 0)
  {
continue;
}

for(j =0 ; j <64; j++)
{
if(table_channels[i].policy[j].type == 0)
{
continue;
}

MY_DEBUG_LOG("[ReadFile]:ID:%d, AppID:%d, used:%d, policy_id:%d , type:%x,  IsWorking:%c,  p_content:%s, IsAllowed:%c.\n", 
i,table_channels[i].AppID,table_channels[i].used,table_channels[i].policy[j].p_id,table_channels[i].policy[j].type,
table_channels[i].policy[j].IsWorking,table_channels[i].policy[j].p_content, table_channels[i].policy[j].IsAllowed);
}
 }


fclose(fp);

MY_DEBUG_LOG("chn_read_file():read from the file start end...\n");

}


现在出现问题,请教网上各位高手:
在一个程序中可以正确执行上面的两个操作,并用日志的形式打印数据,是正确的;可是在其它地方调用void chn_read_file()函数时候,并用日志形式打印数据,却显示的是错误的数据(具体错误: allowed_ip结构体,和 policy结构体中的数据是错误的,随机生成的,也就是没从文件中正确读出来)函数我用的一样,为什么会出现这种情况?

15 个解决方案

#1


哥们,这么长久给20分?

不过帮你顶。

#2


up

#3


有没有字符对齐的问题?

#4


打错了“字节对齐”

#5


很有可能是内存没有对齐的原因,字节错位导致读出的内容混乱。

#6


考虑内存的字节对齐问题,搂主可以把那个结构体拆分一下,或者在读取的时候,写入的时候不用读写入那么多,而是用for循环,每次写入一个结构体的内容


//  fwrite(table_channels, sizeof(TABLE_CHANNEL), 256, fp);
for (int i = 0; i < 256; i++)
{
    fwrite(table_channels[i], sizeof(TABLE_CHANNEL), 1, fp);
}

这样会好一点,因为你的结构体本身的字节就很大,我这边vc6.0下是85780的字节,再去乘以256,那就更大了

#7


太长了 
帮顶了啊

#8


结构体对齐的问题。

#9


typedef struct{
    int used; //0 for unused
    int AppID; 
    /*
           00 "系统",
           01 "HTTP应用",
        02 "SMTP应用",
        03 "POP3应用",
        04 "FTP应用",
        05 "TELNET应用",
        06 "NULL ",
        07 "用户自定义应用",
        08 "TCP空白协议",
        09 "UDP应用",
        0a "ORACLE数据库应用",
        0b "SQL Server 数据库应用",
        0c "邮件服务器与邮件服务器应用",
    */
    char SourceIP[20];
    short SourcePort;
 short Temp1;
    char DestIP[20];
    short DestPort;
    char SourceType; //I for inner;O for outter
    char IsDestProxyMode;
    short MaxConn;
    char IsWorking; 
            // 'Y' for "自动启用,现启用"
            //'N' for "自动启用,现停用"
            //'U' for "手动启用,现停用"
            //'W' for "手动启用,现启用"
       char IsAuth;
        // 0 for no auth
        // 1  for auth
    char Temp2;
    char name[20];
        
    UINT16 InnerPort; //for udp
    UINT16 OuterPort;
    
    char IsAllowed; //安全策略黑白指示
                  // 'Y' for 白
                  // 'N' for 黑
     char Temp3;
        char FromTime[8][8];
     char ToTime[8][8];
     char WeekDay[8][8];


     //for udp allowed ip
     unsigned int inner_udp_ip[256];
     unsigned int outer_udp_ip[256];

     //for tcp allowed ip
     struct IP {
      char ip[255];
      char Temp4;
      int    black_white;
         } allowed_ip[256];
      
     struct POLICY {
        long p_id;
         short type;
        char IsWorking;
        char Temp5;
        char p_content[255];
        char IsAllowed;
         } policy[64];     
}TABLE_CHANNEL;

LZ可以试下,我这没调试环境,不能帮你测试,谢谢。

#10


引用 6 楼 jernymy 的回复:
考虑内存的字节对齐问题,搂主可以把那个结构体拆分一下,或者在读取的时候,写入的时候不用读写入那么多,而是用for循环,每次写入一个结构体的内容

C/C++ code//  fwrite(table_channels, sizeof(TABLE_CHANNEL), 256, fp);for (int i=0; i<256; i++)
{
    fwrite(table_channels[i],sizeof(TABLE_CHANNEL),1, fp);
}
这样会好一点,因为你的结构体本身的字节就很大,我这边vc6.0下是85780的字节,再去乘以256,那就更大了

这个我已经试过了,还是不行

#11


引用 9 楼 tanmeining 的回复:
typedef struct{
    int used; //0 for unused
    int AppID;
    /*
          00 "系统",
          01 "HTTP应用",
        02 "SMTP应用",
        03 "POP3应用",
        04 "FTP应用",
        05 "TELNET应用",
        06 "NULL ",
        07 "用户自定义应用",
        08 "TCP空白协议",
        09 "UDP应用",
        0a "ORACLE数据库应用",
        0b "SQL Server 数据库应用",
        0c "邮件服务器与邮件服务器应用",
    */
    char SourceIP[20];
    short SourcePort;
short Temp1;
    char DestIP[20];
    short DestPort;
    char SourceType; //I for inner;O for outter
    char IsDestProxyMode;
    short MaxConn;
    char IsWorking;
            // 'Y' for "自动启用,现启用"
            //'N' for "自动启用,现停用"
            //'U' for "手动启用,现停用"
            //'W' for "手动启用,现启用"
      char IsAuth;
        // 0 for no auth
        // 1  for auth
    char Temp2;
    char name[20];
       
    UINT16 InnerPort; //for udp
    UINT16 OuterPort;
   
    char IsAllowed; //安全策略黑白指示
                  // 'Y' for 白
                  // 'N' for 黑
    char Temp3;
        char FromTime[8][8];
    char ToTime[8][8];
    char WeekDay[8][8];


    //for udp allowed ip
    unsigned int inner_udp_ip[256];
    unsigned int outer_udp_ip[256];

    //for tcp allowed ip
    struct IP {
      char ip[255];
      char Temp4;
      int    black_white;
        } allowed_ip[256];
     
    struct POLICY {
        long p_id;
        short type;
        char IsWorking;
        char Temp5;
        char p_content[255];
        char IsAllowed;
        } policy[64];   
}TABLE_CHANNEL;

LZ可以试下,我这没调试环境,不能帮你测试,谢谢。
加临时变量是实现什么功能?

#12


 我是进来学习的

#13


是在同一台机器上吗?有可能机器字节序不一样,二进制数据就变了

#14


引用 13 楼 zhengaw 的回复:
是在同一台机器上吗?有可能机器字节序不一样,二进制数据就变了

就在同一台机器上,大哥怎么修改?

#15


很有参考价值

#1


哥们,这么长久给20分?

不过帮你顶。

#2


up

#3


有没有字符对齐的问题?

#4


打错了“字节对齐”

#5


很有可能是内存没有对齐的原因,字节错位导致读出的内容混乱。

#6


考虑内存的字节对齐问题,搂主可以把那个结构体拆分一下,或者在读取的时候,写入的时候不用读写入那么多,而是用for循环,每次写入一个结构体的内容


//  fwrite(table_channels, sizeof(TABLE_CHANNEL), 256, fp);
for (int i = 0; i < 256; i++)
{
    fwrite(table_channels[i], sizeof(TABLE_CHANNEL), 1, fp);
}

这样会好一点,因为你的结构体本身的字节就很大,我这边vc6.0下是85780的字节,再去乘以256,那就更大了

#7


太长了 
帮顶了啊

#8


结构体对齐的问题。

#9


typedef struct{
    int used; //0 for unused
    int AppID; 
    /*
           00 "系统",
           01 "HTTP应用",
        02 "SMTP应用",
        03 "POP3应用",
        04 "FTP应用",
        05 "TELNET应用",
        06 "NULL ",
        07 "用户自定义应用",
        08 "TCP空白协议",
        09 "UDP应用",
        0a "ORACLE数据库应用",
        0b "SQL Server 数据库应用",
        0c "邮件服务器与邮件服务器应用",
    */
    char SourceIP[20];
    short SourcePort;
 short Temp1;
    char DestIP[20];
    short DestPort;
    char SourceType; //I for inner;O for outter
    char IsDestProxyMode;
    short MaxConn;
    char IsWorking; 
            // 'Y' for "自动启用,现启用"
            //'N' for "自动启用,现停用"
            //'U' for "手动启用,现停用"
            //'W' for "手动启用,现启用"
       char IsAuth;
        // 0 for no auth
        // 1  for auth
    char Temp2;
    char name[20];
        
    UINT16 InnerPort; //for udp
    UINT16 OuterPort;
    
    char IsAllowed; //安全策略黑白指示
                  // 'Y' for 白
                  // 'N' for 黑
     char Temp3;
        char FromTime[8][8];
     char ToTime[8][8];
     char WeekDay[8][8];


     //for udp allowed ip
     unsigned int inner_udp_ip[256];
     unsigned int outer_udp_ip[256];

     //for tcp allowed ip
     struct IP {
      char ip[255];
      char Temp4;
      int    black_white;
         } allowed_ip[256];
      
     struct POLICY {
        long p_id;
         short type;
        char IsWorking;
        char Temp5;
        char p_content[255];
        char IsAllowed;
         } policy[64];     
}TABLE_CHANNEL;

LZ可以试下,我这没调试环境,不能帮你测试,谢谢。

#10


引用 6 楼 jernymy 的回复:
考虑内存的字节对齐问题,搂主可以把那个结构体拆分一下,或者在读取的时候,写入的时候不用读写入那么多,而是用for循环,每次写入一个结构体的内容

C/C++ code//  fwrite(table_channels, sizeof(TABLE_CHANNEL), 256, fp);for (int i=0; i<256; i++)
{
    fwrite(table_channels[i],sizeof(TABLE_CHANNEL),1, fp);
}
这样会好一点,因为你的结构体本身的字节就很大,我这边vc6.0下是85780的字节,再去乘以256,那就更大了

这个我已经试过了,还是不行

#11


引用 9 楼 tanmeining 的回复:
typedef struct{
    int used; //0 for unused
    int AppID;
    /*
          00 "系统",
          01 "HTTP应用",
        02 "SMTP应用",
        03 "POP3应用",
        04 "FTP应用",
        05 "TELNET应用",
        06 "NULL ",
        07 "用户自定义应用",
        08 "TCP空白协议",
        09 "UDP应用",
        0a "ORACLE数据库应用",
        0b "SQL Server 数据库应用",
        0c "邮件服务器与邮件服务器应用",
    */
    char SourceIP[20];
    short SourcePort;
short Temp1;
    char DestIP[20];
    short DestPort;
    char SourceType; //I for inner;O for outter
    char IsDestProxyMode;
    short MaxConn;
    char IsWorking;
            // 'Y' for "自动启用,现启用"
            //'N' for "自动启用,现停用"
            //'U' for "手动启用,现停用"
            //'W' for "手动启用,现启用"
      char IsAuth;
        // 0 for no auth
        // 1  for auth
    char Temp2;
    char name[20];
       
    UINT16 InnerPort; //for udp
    UINT16 OuterPort;
   
    char IsAllowed; //安全策略黑白指示
                  // 'Y' for 白
                  // 'N' for 黑
    char Temp3;
        char FromTime[8][8];
    char ToTime[8][8];
    char WeekDay[8][8];


    //for udp allowed ip
    unsigned int inner_udp_ip[256];
    unsigned int outer_udp_ip[256];

    //for tcp allowed ip
    struct IP {
      char ip[255];
      char Temp4;
      int    black_white;
        } allowed_ip[256];
     
    struct POLICY {
        long p_id;
        short type;
        char IsWorking;
        char Temp5;
        char p_content[255];
        char IsAllowed;
        } policy[64];   
}TABLE_CHANNEL;

LZ可以试下,我这没调试环境,不能帮你测试,谢谢。
加临时变量是实现什么功能?

#12


 我是进来学习的

#13


是在同一台机器上吗?有可能机器字节序不一样,二进制数据就变了

#14


引用 13 楼 zhengaw 的回复:
是在同一台机器上吗?有可能机器字节序不一样,二进制数据就变了

就在同一台机器上,大哥怎么修改?

#15


很有参考价值