C中使用fread和fwrite函数出现的问题,熟悉这两个函数的朋友请进

时间:2022-02-26 23:15:05
老板要做一个能够支持不同OS多个平台编译器的程序,不得已又得用回纯C,习惯了Windows下封装好的东西以后,感觉狂不舒服:( 今天遇到一个问题,虽然已经解决,不过本着知其然还要之其所以然的精神,特有此一问~~~

在使用fread和fwrite函数的时候,如果文件打开方式不是二进制方式,在写入unsigned char类型的数据时,会凭空多读或多写一些数据(通常从第二个lpbuf块开始),感觉多读或多写的字符数量是随机产生,请问哪位研究过fread和fwrite函数,麻烦解答一下。
谢谢

9 个解决方案

#1


fwrite fread用于二进制文件读写
如果不用二进制形式打开.会发生意想不到的转换
比如 数据间的空格不再被当作数据的分隔了,也会被存入到数据中

#2


那是微软的fopen函数的BUG,楼主可以参看这两篇:
http://community.csdn.net/Expert/topic/5504/5504186.xml?temp=.458111
http://community.csdn.net/Expert/topic/5609/5609820.xml?temp=.8120539

#3


以前也遇到过这种问题,当对文本文件进行写入时,用文本方式写入没有问题,但如果是写入结构体等时却用文本方式写入时,就很可能在文件中加入一些不可预料的分隔符,这时如果从前向后读取结构体的数据,而且是一个一个的顺序读取,那么没有任何问题,但是如果要随机读取的话,那就会很可能出问题,不能正常读取到结构体的数据,而且当时要求的是从后向前读取结构体的内容,这时读到一半时,结构体的数据就出现了错误。后来改成了用二进制方式操作文件,写入和读取都用二进制方式,结果可以随意的在文件中随机读取结构体的内容都没有发生错误,所以猜测是用文本方式进行操作时,可能会在文件中加入一些与文本有关的符号。

#4


在使用fread和fwrite函数的时候,如果文件打开方式不是二进制方式,在写入unsigned char类型的数据时,会凭空多读或多写一些数据(通常从第二个lpbuf块开始),感觉多读或多写的字符数量是随机产生,请问哪位研究过fread和 fwrite函数,麻烦解答一下。
============================
关键在于 文件操作方式 的区别。
fread和 fwrite 必须使用 2进制操作方式,否则操作的字节数【可能】不正确。

原因是 2进制操作时候,
操作不考虑字符意义,
纯粹操作字节流。
也就是操作的的数据按字节 “流”向 文件(或者读取出来),
但是这个字节的意义不予考虑,
所以参数指定多少长度,就读写多少字节。

但是文本方式不同,
这种操作方式下,考虑字符意义,而不是纯粹考虑字节流。
一个常见的例子,\n 在win下,文本方式操作,
写文件的时候,根据字符意义,会在文件中写入两个字符 \r\n
而文件中的 \r\n 在文本方式读取的时候, 会根据字符意义被转换成\n一个字符【如果是2进制读取的话,这里读取的就是两个字符】

#5



    我想,楼主所说的问题恐怕与程序代码文件打开方式无关,而与你在程序外部打开文件方式有关,也就是说文件类型(扩展名)有关,理由是:
    在C中,二进制和文本打开方式的原理其实是一样的,只不过文本文件方式在读写时会发生对控制字符的进行转义,譬如\n写入会转换为0x0d0a,而读取时,遇到0x0d0a又会转换为\n,所以文本文件只是二进制文件的一个特例,但是这个特例的字符转义是靠读写函数完成的,而楼主是用二进制读写函数进行读写的,决不会发生字符转义,所以,该问题与打开方式无多大关系。
    既然无关,为什么楼主感觉“会凭空多读或多写一些数据”呢,这应该是你在程序外部打开文件不当造成的,比如说,用记事本打开,由于文件的本质是二进制形式的(没有字符转义),一些控制字符被记事本转义了,所有0x20下的不可见控制字符会发生作用,如\0x9会变成制表符,0x0d0a会换行等,即使没发生作用,也是一个小黑方块。

#6


回楼上的,微软的libc确实存在这样的问题(至少俺亲自在VC6上遇到),不信的话可以自己试验哦!
下面是俺刚来CSDN时碰到的一个典型例子:
http://community.csdn.net/Expert/topic/5504/5504186.xml?temp=.458111

#7


呵呵,那我就不清楚了,我从不用VC,我只是从几种C语言函数源码分析的,比如说TC

#8


tc的源代码?哪来的?
可以给俺瞅瞅不?

#9


tc的源代码?哪来的?
=========================================================
tc函数的原代码,不是tc的原代码,大多数都是插入汇编。10年前买的,现在不在身边

#1


fwrite fread用于二进制文件读写
如果不用二进制形式打开.会发生意想不到的转换
比如 数据间的空格不再被当作数据的分隔了,也会被存入到数据中

#2


那是微软的fopen函数的BUG,楼主可以参看这两篇:
http://community.csdn.net/Expert/topic/5504/5504186.xml?temp=.458111
http://community.csdn.net/Expert/topic/5609/5609820.xml?temp=.8120539

#3


以前也遇到过这种问题,当对文本文件进行写入时,用文本方式写入没有问题,但如果是写入结构体等时却用文本方式写入时,就很可能在文件中加入一些不可预料的分隔符,这时如果从前向后读取结构体的数据,而且是一个一个的顺序读取,那么没有任何问题,但是如果要随机读取的话,那就会很可能出问题,不能正常读取到结构体的数据,而且当时要求的是从后向前读取结构体的内容,这时读到一半时,结构体的数据就出现了错误。后来改成了用二进制方式操作文件,写入和读取都用二进制方式,结果可以随意的在文件中随机读取结构体的内容都没有发生错误,所以猜测是用文本方式进行操作时,可能会在文件中加入一些与文本有关的符号。

#4


在使用fread和fwrite函数的时候,如果文件打开方式不是二进制方式,在写入unsigned char类型的数据时,会凭空多读或多写一些数据(通常从第二个lpbuf块开始),感觉多读或多写的字符数量是随机产生,请问哪位研究过fread和 fwrite函数,麻烦解答一下。
============================
关键在于 文件操作方式 的区别。
fread和 fwrite 必须使用 2进制操作方式,否则操作的字节数【可能】不正确。

原因是 2进制操作时候,
操作不考虑字符意义,
纯粹操作字节流。
也就是操作的的数据按字节 “流”向 文件(或者读取出来),
但是这个字节的意义不予考虑,
所以参数指定多少长度,就读写多少字节。

但是文本方式不同,
这种操作方式下,考虑字符意义,而不是纯粹考虑字节流。
一个常见的例子,\n 在win下,文本方式操作,
写文件的时候,根据字符意义,会在文件中写入两个字符 \r\n
而文件中的 \r\n 在文本方式读取的时候, 会根据字符意义被转换成\n一个字符【如果是2进制读取的话,这里读取的就是两个字符】

#5



    我想,楼主所说的问题恐怕与程序代码文件打开方式无关,而与你在程序外部打开文件方式有关,也就是说文件类型(扩展名)有关,理由是:
    在C中,二进制和文本打开方式的原理其实是一样的,只不过文本文件方式在读写时会发生对控制字符的进行转义,譬如\n写入会转换为0x0d0a,而读取时,遇到0x0d0a又会转换为\n,所以文本文件只是二进制文件的一个特例,但是这个特例的字符转义是靠读写函数完成的,而楼主是用二进制读写函数进行读写的,决不会发生字符转义,所以,该问题与打开方式无多大关系。
    既然无关,为什么楼主感觉“会凭空多读或多写一些数据”呢,这应该是你在程序外部打开文件不当造成的,比如说,用记事本打开,由于文件的本质是二进制形式的(没有字符转义),一些控制字符被记事本转义了,所有0x20下的不可见控制字符会发生作用,如\0x9会变成制表符,0x0d0a会换行等,即使没发生作用,也是一个小黑方块。

#6


回楼上的,微软的libc确实存在这样的问题(至少俺亲自在VC6上遇到),不信的话可以自己试验哦!
下面是俺刚来CSDN时碰到的一个典型例子:
http://community.csdn.net/Expert/topic/5504/5504186.xml?temp=.458111

#7


呵呵,那我就不清楚了,我从不用VC,我只是从几种C语言函数源码分析的,比如说TC

#8


tc的源代码?哪来的?
可以给俺瞅瞅不?

#9


tc的源代码?哪来的?
=========================================================
tc函数的原代码,不是tc的原代码,大多数都是插入汇编。10年前买的,现在不在身边