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

guoshilong 2009-12-07 09:45:16
在项目中我定义了一个结构体数组,头文件如下:

#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结构体中的数据是错误的,随机生成的,也就是没从文件中正确读出来)函数我用的一样,为什么会出现这种情况?
...全文
1534 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
d_luo 2012-08-20
  • 打赏
  • 举报
回复
很有参考价值
jernymy 2009-12-08
  • 打赏
  • 举报
回复
考虑内存的字节对齐问题,搂主可以把那个结构体拆分一下,或者在读取的时候,写入的时候不用读写入那么多,而是用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,那就更大了
hbvanguard 2009-12-08
  • 打赏
  • 举报
回复
很有可能是内存没有对齐的原因,字节错位导致读出的内容混乱。
pf_ma 2009-12-08
  • 打赏
  • 举报
回复
打错了“字节对齐”
pf_ma 2009-12-08
  • 打赏
  • 举报
回复
有没有字符对齐的问题?
guoshilong 2009-12-08
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 zhengaw 的回复:]
是在同一台机器上吗?有可能机器字节序不一样,二进制数据就变了
[/Quote]
就在同一台机器上,大哥怎么修改?
qingyaoli 2009-12-08
  • 打赏
  • 举报
回复
是在同一台机器上吗?有可能机器字节序不一样,二进制数据就变了
匚匚 2009-12-08
  • 打赏
  • 举报
回复
我是进来学习的
guoshilong 2009-12-08
  • 打赏
  • 举报
回复
[Quote=引用 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可以试下,我这没调试环境,不能帮你测试,谢谢。

[/Quote]加临时变量是实现什么功能?
guoshilong 2009-12-08
  • 打赏
  • 举报
回复
[Quote=引用 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,那就更大了
[/Quote]
这个我已经试过了,还是不行
tanmeining 2009-12-08
  • 打赏
  • 举报
回复
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可以试下,我这没调试环境,不能帮你测试,谢谢。
tanmeining 2009-12-08
  • 打赏
  • 举报
回复
结构体对齐的问题。
jianzhibeihang 2009-12-08
  • 打赏
  • 举报
回复
太长了
帮顶了啊
liushiyuyi 2009-12-07
  • 打赏
  • 举报
回复
up
xiaoshun123 2009-12-07
  • 打赏
  • 举报
回复
哥们,这么长久给20分?

不过帮你顶。
C语言之基础 1) C语言之简介 2) C语言之搭建开发环境 3) C语言之第一个简单程序的结构详解 4) C语言之书写规范和注释 5) C语言之数据类型 字符串和格式化输入输出 6) C语言之使用字符串 7) C语言之格式化输出 8) C语言之格式化输入 9) C语言之格式化输入输出整理 10) C语言之基本运算符 11) C语言之其他运算符 12) C语言之表达式和语句 循环语句 13) C语言之while循环语句 14) C语言之do-while循环语句 15) C语言之for循环语句 16) C语言之使用关系运算符和表达式 17) C语言之赋值运算+=、-=、*=、/=、%= 18) C语言之循环嵌套 分支跳转 19) C语言之分支和跳转 if 20) C语言之分支和跳转 if-else 21) C语言之条件运算符 ?: 22) C语言之循环辅助手段:continue 和 break 23) C语言之分支和跳转 switch和break 24) C语言之分支和跳转 goto语句 25) C语言之字符输入/输出和输入确认 指针 26) C语言之初识指针 27) C语言之指针的简单用法 28) C语言之字符串指针详解 数组 29) C语言之定义数组 30) C语言之一维数组的使用 31) C语言之二维数组和多维数组 32) C语言之指向数组的指针 33) C语言之保护数组内容const的使用 34) C语言之指向多维数组的指针 函数 35) C语言之函数的定义和调用 36) C语言之定义带参数的函数 37) C语言之函数之形参和实参 38) C语言之函数之返回值和函数类型 39) C语言之指针做函数参数 40) C语言之数组做函数参数 41)c语言之递归 字符串和字符串函数 42)c语言之字符串I/O 43) C语言之字符串输入/输出 44) C语言之字符串处理函数 文件操作 45) C语言文件是什么 46) C语言之用fopen() 打开文件,关闭文件 fclose() 47) C语言之getc() 和 putc 读写文件 48) C语言文件结尾 49) C语言之fgets() 和 fputs() 50) C语言文件内部指针 51) C语言之rewind() 52) C语言之随机存取 fseek() 和 ftell() 函数 53) C语言之fsetpos和fgetpos 54) C语言之fread() 和 fwrite() 函数 结构体和其他数据形式 55) C语言之结构体的定义和初始化 56) C语言之访问结构体成员 57) C语言之结构数组 58) C语言之结构体指针 59) C语言之结构体做函数参数 60) C语言之把结构体保存文件 已更新至此 61)C语言之联合简介 62)C语言之枚举类型 63)C语言之函数和指针 位操作 64) C语言二进制、位和字节 65)C语言之位运算 66)C语言之打开位 67) C语言之转置位及查看位 68) C语言之左移右移(大结局)
本套教程免费获取地址:www.zixue7.com C语言之基础 1) C语言之简介 2) C语言之搭建开发环境 3) C语言之第一个简单程序的结构详解 4) C语言之书写规范和注释 5) C语言之数据类型 字符串和格式化输入输出 6) C语言之使用字符串 7) C语言之格式化输出 8) C语言之格式化输入 9) C语言之格式化输入输出整理 10) C语言之基本运算符 11) C语言之其他运算符 12) C语言之表达式和语句 循环语句 13) C语言之while循环语句 14) C语言之do-while循环语句 15) C语言之for循环语句 16) C语言之使用关系运算符和表达式 17) C语言之赋值运算+=、-=、*=、/=、%= 18) C语言之循环嵌套 分支跳转 19) C语言之分支和跳转 if 20) C语言之分支和跳转 if-else 21) C语言之条件运算符 if-elseif 和 ?: 22) C语言之循环辅助手段:continue和 break 23) C语言之分支和跳转 switch和break 24) C语言之分支和跳转 goto语句 25) C语言之字符输入/输出和输入确认 指针 26) C语言之初识指针 27) C语言之指针的简单用法 28) C语言之字符串指针详解 数组 29) C语言之定义数组 30) C语言之一维数组的使用 31) C语言之二维数组和多维数组 32) C语言之指向数组的指针 33) C语言之保护数组内容const的使用 34) C语言之指向多维数组的指针 函数 35) C语言之函数的定义和调用 36) C语言之定义带参数的函数 37) C语言之函数之形参和实参 38) C语言之函数之返回值和函数类型 39) C语言之指针做函数参数 40) C语言之数组做函数参数 41) C语言之函数之递归详解 字符串和字符串函数 42) C语言之字符串表示和字符串I/O 43) C语言之字符串输入/输出 44) C语言之字符串处理函数 操作文件 45) C语言文件是什么 46) C语言之用fopen() 打开文件,关闭文件 fclose() 47) C语言之getc() 和 putc 读写文件 48) C语言文件结尾 49) C语言之fgets() 和 fputs() 50) C语言文件内部指针 51) C语言之rewind() 52) C语言之随机存取 fseek()和 ftell() 函数 53) C语言之fsetpos和fgetpos 54) C语言之fread() 和 fwrite() 函数 结构体和其他数据形式 55) C语言之结构体的定义和初始化 56) C语言之访问结构体成员 57) C语言之结构数组 58) C语言之结构体指针 59) C语言之结构体做函数参数 60) C语言之把结构体保存文件 61) C语言之联合简介 62) C语言之枚举类型 63) C语言之函数和指针 位操作 64) C语言二进制、位和字节 65) C语言之位运算 66) C语言之打开位 67) C语言之转置位及查看位 68) C语言之左移右移(大结局)

69,371

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧