fopen参数@windows和linux的区别

ぐ巨炮叔叔 提交于 2020-02-29 08:16:54
        作为文件的数据,在计算机中都是以二进制的形式存储的。因此,对于文本文件和二进制文件的区分,不是在物理上的,而是在逻辑上的。
        在开发时,遇到一个小问题,代码在linux下运行读写文件正常,而在windowns下读写文件出现异常。
【现象】
         在linux中使用fopen第2个参数为"r"或"w"打开二进制文件后读写没有任何问题,但将代码移到windows后,读写却出现了异常。将参数改成"rb"和"wb"后,读写正常。
【原因】
        在学习C语言文件操作后,我们知道打开文件的函数是fopen,也知道它的第二个参数mode是标志字符串。其中,如果字符串中出现'b',则表明是以打开二进制(binary)文件,否则是打开文本文件。具体如下:
'r' 只读方式打开,将文件指针指向文件头,如果文件不存在,则File返回空。
'r+' 读写方式打开,将文件指针指向文件头,如果文件不存在,则File返回空。 
'w' 写入方式打开,将文件指针指向文件头并将文件大小截为零。如果文件不存在则尝试创建之。 
'w+' 读写方式打开,将文件指针指向文件头并将文件大小截为零。如果文件不存在则尝试创建之。 
'a' 写入方式打开,将文件指针指向文件末尾。如果文件不存在则尝试创建之。 
'a+' 读写方式打开,将文件指针指向文件末尾。如果文件不存在则尝试创建之。 
'x' 创建并以写入方式打开,将文件指针指向文件头。如果文件已存在,则 fopen() 调用失败并返回 FALSE。 
'x' 创建并以写入方式打开,将文件指针指向文件头。如果文件已存在,则 fopen() 调用失败并返回 FALSE。
'b' 使用字符b作为文件类型的判断,是否是binary(二进制)文件。
        Windows和DOS系统 中,狭义的文本文件是指扩展名为txt的文件。实际上,那些没有规定格式的,由可理解的的ASCII以及其他编码文字组成的文件都是文本文件,如C源程序文件,HTML超文本,XML。除此之外的其
他文件都是二进制文件,如Word文件DOC,图像格式文件JPG。

        但是,所谓使用fopen标志打开文本文件与二进制文件的,实质就是--以文本方式或二进制方式打开文件。因为我们用这两种方式都可以任意的打开文件。
        即使这样,为什么还要区分这两种方式呢?
        这是因为这两种方式在读写文件时的操作是不一样的。
        二进制方式很简单,读文件时,会原封不动的读出文件的全部内容,写的时候,也是把内存缓冲区的内容原封不动的写到文件中。文本方式就不一样了,在读文件时,会将换行符号CRLF(0x0D 0x0A)全部转换成单个的0x0A,并且当遇到结束符CTRLZ(0x1A)时,就认为文件已经结束。相应的,写文件时,会将所有的0x0A换成0x0D0x0A。(针对windows系统)所以,若使用文本方式打开二进制文件时,就很容易出现文件读不完整,或内容不对的错误。即使是用文本方式打开文本文件,也要谨慎使用,比如复制文件,就不应该使用文本方式。要特别注意的是,上面这样的说法仅适用于DOS和Windows系统
         Unix和其他一些系统中,没有文本方式和二进制方式的区分,使不使用'b'标志都是一样的。这是由于不同操作系统对文本文件换行符的定义,和C语言中换行符的定义有所不同而造成的。如上文已提到,DOS和Windows系统使用CRLF(0x0D 0x0A)双字节作为文本文件换行符,而Unix文本文件的换行符只有一个字节LF(0x0A)为。在C语言中,也是以LF即'\n'为换行符。由于DOS/Windows定义的换行符和C语言的不一致,C语言的标准输入输出函数进行读写文本文件时,就进行了CRLF->LF的转换。而Unix的定义和C语言的是一样的,就不必转换了。

那么,为什么会有定义不一致的情况呢,这纯属历史原因。当初C是在Unix上发展的,对换行的定义自然就一样了。其后C被引入到DOS系统,为了使原有的C程序能不加修改的读写DOS的文本文件,所以就在文件读写上做了修改。随着DOS/Windows成为主流平台,这个当初为了兼容而做的修改给众多的C语言开发者添了这样一个小小的麻烦。


易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!