正在进行的项目中有个日志存储模块,需要在设备端将日志数据写到存储介质——其实就是硬盘,就是一个文件。在我测试时,发现上位机读取到的日志数据不全,明明登陆到设备看有100多KB,但读到的日志才2行,肯定有问题,另外,设备存储的日志文件内容也有乱码出现。因为这个模块在其它项目一直使用,一直OK,现在出问题了,很郁闷。而且该模块嵌入到其它大的功能模块,后来跟踪、独立测试,终于找到问题原因。当这个“小”问题解决时,都已经过了大半天了,架构如果复杂,以至于要细细跟踪,不同平台的差别,以至于无人注意。

以前使用的是ARM平台,使用的存储介质是eeprom;而现在是X86平台,没有了eeprom,所有的数据,存储在硬盘上,而在linux上看,都是文件。这点,在项目初期,没什么人留意因平台差别而带来的影响、工作量——不要怪我,因为那时我正被内核和根文件系统搞得头大,而且又没参与架构代码的编写。

问题出现有2个原因,一是没注意eeprom和普通文件的操作上的区别,二是打开文件的框架代码封装得十分隐密(正因为封装得好,使人认为操作所有“文件”的代码都一样)。

日志模块抽象后的示例代码如下:

// 打开文件
fp = fopen(MYFILE, "a+");
// 读头部数据
fread(MyHead, 1, sizeof(MyHead), fp)
// 处理其它
...
// 写入数据
fwrite(szText, 1, sizeof(szText), fp)
// 更新头部数据
...
// 回到头部
fseek(fp, 0, SEEK_SET)
// 更新头部
fwrite(MyHead, 1, sizeof(MyHead), fp)

该模块使用文件前面的数据作为头部,保留了日志长度等关键信息。上位机读取才得到2行,是因为该头部中的日志长度字段除了第一次更新外,后面所有的写操作都没有更新——代码的确有更新“头部”,但即不是正在的头部,而是在日志数据后面添加。简单理解就是,最后的fseek并没有回到文件开头处,而是在文件结尾,于是fwrite就直接写到文件最后,这也解释了日志文件为什么会有乱码,因为那是头部数据。

查了fopen的参数,“a+”关键点如下:

“Repositioning operations (fseek, fsetpos, rewind) affects the next input operations, but output operations move the position back to the end of file. ”

这句话最后是说光标都回到文件的末尾。因此,使用“a+”打开文件是不正确的。

网上有文章(http://blog.csdn.net/flyfy1/article/details/4763347)说得很好,就直接抄下来了:

r+ 和 w+ 的区别:

r+ 是可以直接写在文件上,读取和写入的光标都在文件开头。

w+ ,如果文件已经存在,将建立一个新文件覆盖原文件(很缺德啊……),并且支持读取。

a+ 和 r+:

a+只能在文件最后补充,光标在结尾。

r+可以覆盖前面的内容,光标在开头

最终的解决方法是,将原来代码的“a+”n改为“r+”,只改一个字符,即可解决问题。修改很简单,但知道修改的原因却要经过一番努力——而这,就是不为人知的背后的辛酸。

参考资料:

http://www.cplusplus.com/reference/cstdio/fopen/

http://blog.csdn.net/flyfy1/article/details/4763347

李迟,2015年1月17日 中午

遇到一个打开文件方式“w+”和“a+”的问题相关推荐

  1. linux下vim 打开文件方式

    vim 打开文件方式 linux下使用vim打开文件可以使用两种方法: 一,  直接使用vim     XXX.txt   打开文件为xxx.txt的文件 二,在已经进入vim之后,要打开新的文件: ...

  2. python创建打开文件-python打开文件方式

    python中的open()函数用于打开一个文件,创建file对象,相关方法才可以调用它进行读写 语法:open(name,[,model[,buffering]]) 模式描述 r 以只读方式打开文件 ...

  3. python所有文件都能用文本方式打开_python 打开文件方式讲解、常用读写操作指令(全)以及读写常见问题...

    python读写方式 python的读写,在实际应用中还是很广泛的,有必要系统性的学习一下,以便于处理问题时的抉择和对现象的合理解释.例如,python用logging写入日志文件默认的读写方式是&q ...

  4. fopen_s打开文件方式的选择

    写一个程序,用socket套接字传递一个图片文件(大小:241KB),发送过去后,在生成图片时,大小变为了242KB,自然,图片文件无法预览. 后经查找,在生成图片时,打开文件操作如下: errno_ ...

  5. open函数打开文件方式

    r: 以只读方式打开文件.文件的指针将会放在文件的开头.这是**默认模式**. rb: 以二进制格式打开一个文件用于只读.文件指针将会放在文件的开头.这是默认模式. r+: 打开一个文件用于读写.文件 ...

  6. Python打开文件时'w'与'wb','r'与'rb'的区别(2019年1月3日)

    文件读写中后面的参数:w,r,wt,rt,wb,rb,都是python里面文件操作的模式. 1.w是写模式,r是读模式. 2.t是windows平台特有的所谓text mode(文本模式),区别在于会 ...

  7. php 打开文件方式

    php打开文件的方式 r:只读,文件指针指向文件头 例:fopen('test.txt','r'),此时文件指针在文件头,读取文件从第一个字符处开始向后读取内容.不可写入文件.不可创建文件 r+:读写 ...

  8. 为什么下载了应用软件,在打开相对应文件时候,打开方式里却不提示,而且设置默认打开文件方式也不行?

    原因: 可能是你移动了程序,导致程序路径和注册表路径不一致! 解决方法: 1.这里我随便找一个应用程序举例,右击打开软件"属性",复制 "目标路径" 2.点击电 ...

  9. c语言open函数打开文件方式,Linux中C语言open函数打开或创建文件详细讲解

    Linux中C语言open函数打开或创建文件详细讲解 Linux中C语言open函数打开或创建文件详细讲解 头文件: #include #include #include 函数原型: int open ...

最新文章

  1. jsp简介mysql_个人知识管理系统的设计与实现(JSP,MySQL)(含录像)
  2. python 向量余弦相似度
  3. Python连接MYSQL,并做查询操作
  4. OFBiz + Opentaps 目录管理 四. 产品(二)可配置产品
  5. linux提升网络实时性,通过调整Linux内核参数提升网络性能
  6. 利用python对微信云数据库_如何用python看看女神的微信百度云里面有啥?
  7. mysql 数据缓冲区,MySQL写入缓冲区在数据库中的作用( Change Buffer )
  8. 输出奇数和偶数(Java)
  9. 关于JavaScript中apply与call的用法意义及区别(转)
  10. 拓端tecdat|R语言时变面板平滑转换回归模型TV-PSTR分析债务水平对投资的影响
  11. 最佳Bilibili下载工具及下载Bilibili视频方法
  12. Java业内主流框架你知道吗?SSH和SSM有什么区别?
  13. PDF文件怎么编辑内容
  14. Linux安装Tab键补全功能
  15. sqlserver连接池及查看连接数相关
  16. 【转】关于测试工程师的几个笑话
  17. 福州大学计算机学硕分数,2021年福州大学考研录取分数线应该在哪里查询?
  18. 健壮I/O读写函数——RIO包
  19. 孪生素数的最优解(应该)
  20. 基于AIOT综合能源管控平台开发探讨

热门文章

  1. iPhone 14 Pro系列传出好消息,有望实现8GB内存自由
  2. Meta最快明年推出智能手表 挑战下一代Apple Watch
  3. 别人家的公司!雷军发红包 人均39万
  4. 英特尔Bridge技术加持下 Windows 11 PC也能运行手机应用
  5. 小米“618”战报:全平台支付金额破190亿,同比增长90%
  6. 苹果WWDC2021终极剧透!新款Macbook Pro外观大改 iOS 15将发布
  7. 理想汽车4月交付5539辆 累计交付51715辆
  8. 开盘暴涨193.9%,市值1.39万亿港元!快手正式上市
  9. 官宣了!百度36亿美元收购YY直播,一个用户“值”87.4美元
  10. 华为P40渲染图再曝光:果然是年度真旗舰