可以使用fwrite()将一个结构体写入文件:
  fwrite(&some_struct,sizeof somestruct,1,fp);
对应的fread函数可以再把它读出来,此处fwrite受到一个结构的指针并把这个结构的内存映像作为字节流写入文件。sizeof操作符计算出结构占用的字节数。
但是这样用内存映像写出的数据文件却是不能够移植的,尤其是当结构中包含浮点成员或指针的时候。结构的内存布局跟机器和编译器都有关。不同的编译器可能使用不同数量的填充位,不同机器上基本类型的大小和字节顺序也不尽相同。因此,作为内存映像写出的结构在别的机器上(甚至是被别的编译器编译之后)不一定能被读回来。
  同时注意如果结构包含任何指针(char*字符串或指向其他数据结构的指针),则只有指针值会被写入文件。当它们再次被读回来的时候可能已经失效。最后为了广泛的可移植性,你必需用“b”标志打开文件。

读写结构体的程序如下:

将结构体写入文件:

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. typedef struct {
  4. char c;
  5. int h;
  6. short n;
  7. long m;
  8. float f;
  9. double d1;
  10. char *s;
  11. double d2;
  12. }st;
  13. int main(void)
  14. {
  15. FILE *fp;
  16. st sa,sb;
  17. char *str="abcdefg";
  18. sa.c='K';
  19. sa.h=-3;
  20. sa.n=20;
  21. sa.m=100000000;
  22. sa.f=33.32f;
  23. sa.d1=78.572;
  24. sa.d2=33.637;
  25. sa.s=str;
  26. fp=fopen("st.txt","w+");
  27. if(!fp)
  28. {
  29. printf("errror!\n");
  30. exit(-1);
  31. }
  32. printf("sa:c=%c,h=%d,n=%d,m=%d,f=%f,d1=%f,s=%s,d2=%f\n",sa.c,sa.h,sa.n,sa.m,sa.f,sa.d1,sa.s,sa.d2);
  33. printf("sizeof(sa)=%d:&c=%x,&h=%x,&n=%x,&m=%x,&f=%x,&d1=%x,&s=%x,&d2=%x\n",sizeof(sa),&sa.c,&sa.h,&sa.n,&sa.m,&sa.f,&sa.d1,&sa.s,&sa.d2);
  34. fwrite(&sa,sizeof(sa),1,fp);
  35. rewind(fp);
  36. fread(&sb,sizeof(sb),1,fp);
  37. printf("sb:c=%c,h=%d,n=%d,m=%d,f=%f,d1=%f,s=%s,d2=%f\n",sb.c,sb.h,sb.n,sb.m,sb.f,sb.d1,sb.s,sb.d2);
  38. fclose(fp);
  39. return 0;
  40. }

从文件中读出结构体:

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. typedef struct {
  4. char c;
  5. int h;
  6. short n;
  7. long m;
  8. float f;
  9. double d1;
  10. char *s;
  11. double d2;
  12. }st;
  13. int main(void)
  14. {
  15. FILE *fp;
  16. st sb;
  17. fp=fopen("st.txt","r");
  18. if(!fp)
  19. {
  20. printf("errror!\n");
  21. exit(-1);
  22. }
  23. fread(&sb,sizeof(sb),1,fp);
  24. printf("sb:c=%c,h=%d,n=%d,m=%d,f=%f,d1=%f,s=%s,d2=%f\n",sb.c,sb.h,sb.n,sb.m,sb.f,sb.d1,sb.s,sb.d2);
  25. printf("sizeof(sb)=%d:&c=%x,&h=%x,&n=%x,&m=%x,&f=%x,&d1=%x,&s=%x,&d2=%x\n",sizeof(sb),&sb.c,&sb.h,&sb.n,&sb.m,&sb.f,&sb.d1,&sb.s,&sb.d2);
  26. fclose(fp);
  27. return 0;
  28. }

在linux平台下的GCC编译器进行编译后的结果如下:

首先是结构体写入文件:

sa:c=K,h=-3,n=20,m=100000000,f=33.320000,d1=78.572000,s=abcdefg,d2=33.637000
sizeof(sa)=40:&c=bfb98a10,&h=bfb98a14,&n=bfb98a18,&m=bfb98a1c,&f=bfb98a20,&d1=bfb98a24,&s=bfb98a2c,&d2=bfb98a30
sb:c=K,h=-3,n=20,m=100000000,f=33.320000,d1=78.572000,s=abcdefg,d2=33.637000

从文件中读出结构体:

sb:c=K,h=-3,n=20,m=100000000,f=33.320000,d1=78.572000,s=���o��,d2=33.637000

sizeof(sb)=40:&c=bfbc9964,&h=bfbc9968,&n=bfbc996c,&m=bfbc9970,&f=bfbc9974,&d1=bfbc9978,&s=bfbc9980,&d2=bfbc9984

在windows xp 平台下利用Visual C++编译器编译后结果如下:

写入结构体:

sa:c=K,h=-3,n=20,m=100000000,f=33.320000,d1=78.572000,s=abcdefg,d2=33.637000
sizeof(sa)=48:&c=12ff28,&h=12ff2c,&n=12ff30,&m=12ff34,&f=12ff38,&d1=12ff40,&s=12ff48,&d2=12ff50
sb:c=K,h=-3,n=20,m=100000000,f=33.320000,d1=78.572000,s=abcdefg,d2=33.637000
读出结构体:

sb:c=K,h=-3,n=20,m=100000000,f=33.320000,d1=78.572000,s=e,d2=33.637000

sizeof(sb)=48:&c=12ff28,&h=12ff2c,&n=12ff30,&m=12ff34,&f=12ff38,&d1=12ff40,&s=12

从上面的结果我们可以得到如下几个结论:

1. 如果结构体中含有指针,是很容易出问题的,从上面的结果中(高亮)部分可以看到字符串的输出结果是不一样的,这说明,在进行写入文件的时候,char*所指向的字符串没有写入文件,只是将指针写入,当从文件中读出结构体,再次得到这个指针的时候,由于程序运行的内存位置变化,所以原来指针所指向的内容也变了,所以输出也变了。

2. 还有一个比较重要的是结构体的内存对其问题(之前也讨论过)。可以看到,不同的编译器采取的方式是不一样的。 gcc中的结构体大小为40字节,而VC下是48个字节。

并且GCC下,结构体内存的起始位置是4的倍数,而VC中是8的倍数。这是因为,结构体的起始地址与其中所包含的拥有最多字节的类型有关。之前也说过,因为GCC的处理方式是如果结构体内有超过4个字节的类型,那么结构体起始位置以4的倍数开始, 而VC中是以最大字节数的为准。

ps:4的倍数就是地址的最低两位是00,8的倍数就是地址最低三位为000

然后我分别在linux下读入winxp写的结构体文件和在winxp下读入linux下写的结构体文件,两个平台下的程序都崩溃了。

c++ 读写结构体到文件的更多相关文章

  1. Demo02_对结构体进行文件读写_张仕传_作业_

    #include <iostream> using namespace std; #define StructArrarySize 5 // 老师数量 #define StudentNum ...

  2. 在FLASH中读写结构体

    在FLASH中读写结构体 注意事项 编程(写数据)地址要对齐 写数据时,我们要指定写入的地址,如果写入地址为非对齐,则会出现编程对齐错误. 比如遵循32位(4字节)地址对齐,你的地址只能是4的倍数.0 ...

  3. C语言文件读写(结构体文件)

    有时候,我们需要将输入的数据存储起来,这时候就需要用到文件,对于C语言而言,文件的读写有多种方式,下面主要是结构体文件的读写,例如student.dat(第一列是学号,第二列是姓名) xiaoming ...

  4. 结构体:探析C#文件方式读写结构体

    最近直在研究Net Micro Framework字体文件(tinyfnt)由于tinyfnt文件头部有段描述数据所以很想 定义个结构体像VC样直接从文件中读出来省得用流个个解析很是麻烦 没有想到在中 ...

  5. cdev成员结构体file_operations文件操作结构的分析

    struct file_operations{ struct module *owner; // 指向拥有该结构的模块的指针,避免正在操作时被卸载,一般为初始化为THIS_MODULES loff_t ...

  6. C语言中FILE是结构体,文件类型的指针

    c语言文件类型指针 我们在定义文件类型指针变量后,称作该指针指向该文件,但本质上,它不是指向一个存储文件信息的结构型变量么?那么我们在用各个函数对所谓的“文件指针”进行操作时,本质上是不是函数通过获取 ...

  7. C语言博客作业--结构体,文件

    1.本章学习总结(2分) 1.1 学习内容总结 (1)结构体如何定义.成员如何赋值 结构体的一般形式为:      struct  结构体名     {      数据类型 成员名1:      数据 ...

  8. 几年前做家教写的C教程(之五专讲结构体与文件操作)

    C语言学习宝典(5) 结构体: 将不同类型的数据组合成为一个有机的整体,这个整体就是一个结构体. 例如: Struct student { Int name; Char sex; Float scor ...

  9. Delphi基础Write写入结构体到文件(使用 file of myrecord就行了,真简单)

    program WriteStruct; {$APPTYPE CONSOLE} uses SysUtils; //写入结构体 type TCustomer = record ID: ]; Code: ...

随机推荐

  1. springboot(十一)-为什么要用springboot

    前言 学习了一段时间springboot,一般都可以在项目中使用springboot开发了.因为springboot的东西并不多,或者说,springboot根本就没有新东西. 好了,现在问一句,我们 ...

  2. 2.7 Go channel

    channel简单示例 package main import ( "fmt" "time" ) //channel的创建,发送,接收 func channe1 ...

  3. $bzoj1021-SHOI2008\ Debt$ 循环的债务 $dp$

    题面描述 \(Alice\).\(Bob\)和\(Cynthia\)总是为他们之间混乱的债务而烦恼,终于有一天,他们决定坐下来一起解决这个问题.不过,鉴别钞票的真伪是一件很麻烦的事情,于是他们决定要在 ...

  4. 未来一年的13大手机APP开发趋势

    无论是欢呼出租车,保存票据,订购披萨还是在线购物,您可以立即联系到什么设备?你的智能手机 这是您需要的朋友,在如何查找信息和简化日常任务方面发挥着不可或缺的作用. 移动技术以光速增长; 我们不能否认手 ...

  5. kafka producer自定义partitioner和consumer多线程

    为了更好的实现负载均衡和消息的顺序性,Kafka Producer可以通过分发策略发送给指定的Partition.Kafka Java客户端有默认的Partitioner,平均的向目标topic的各个 ...

  6. springboot整合spring data jpa 动态查询

    Spring Data JPA虽然大大的简化了持久层的开发,但是在实际开发中,很多地方都需要高级动态查询,在实现动态查询时我们需要用到Criteria API,主要是以下三个: 1.Criteria ...

  7. Mac下使用wireshark解决Interface为空的办法

    Terminal中运行chown <user-name> /dev/bpf*命令 <user-name>处替换为当前mac用户名

  8. Mongodb cassandra 和 Mysql对比

    MongoDBDB.Cassandra和 Mysql对比 1.为什么是Nosql? 1.1 Nosql在大数据处理相对于关系型数据库具有优势 1.1.1                  1. 低延迟 ...

  9. hadoop命令详解

    一.用户命令1.archive命令 (1).什么是Hadoop archives?Hadoop archives是特殊的档案格式.一个Hadoop archive对应一个文件系统目录. Hadoop ...

  10. spring mvc中DispatcherServlet如何得到ModelAndView的

    首先看下面这种张图,这张图说明了spring mvc整体的流程. 本文讲的就是如何从DispatcherServlet中得到ModerAndView的过程. 首先看DispatherServlet这个 ...