fopen按文本方式打开文件和按二进制方式打开文件的区别

本文详细解释了C语言中以文本方式和二进制方式打开文件的区别,特别是这两种方式在读写过程中的特殊处理,以及在不同操作系统下(如Windows与Unix)文件处理的差异。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

   今天在写文件的时候发现fwrite的时候多出了一些乱码,最后发现加个b,以二进制的方式打开文件就解决了,google了.... 特记与此

   在学习C语言文件操作后,我们都会知道打开文件的函数是fopen,也知道它的第二个参数是 标志字符串。其中,如果字符串中出现'b',则表明是以打开二进制(binary)文件,否则是打开文本文件。

  那么什么是文本文件,什么是二进制文件呢? 可能大多数人都没有仔细考虑过。

  在Windows和DOS系统中,狭义的文本文件是指扩展名为txt的文件。实际上,那些没有规定格式的,由可理解的的ASCII以及其他编码文字组成的文件都是文本文件,如C源程序文件,HTML超文本,XML。除此之外的其他文件都是二进制文件,如Word文件DOC,图象格式文件JPG。

  但是,所谓使用fopen标志打开文本文件与二进制文件的说法并不准确。正确的说法应该是--以文本方式和二进制方式打开文件。因为我们用两种方式都可以任意的文件。

  即使这样,为什么还要区分两种方式呢?

  这是因为这两种方式在读写文件时的操作是不一样的。

  二进制方式很简单,读文件时,会原封不动的读出文件的全部內容,写的時候,也是把內存缓冲区的內容原封不动的写到文件中。

  而文本方式就不一样了,在读文件时,会将换行符号CRLF(0x0D 0x0A)全部转换成单个的0x0A,并且当遇到结束符CTRLZ(0x1A)时,就认为文件已经结束。相应的,写文件时,会将所有的0x0A换成0x0D0x0A。所以,若使用文本方式打开二进制文件时,就很容易出现文件读不完整,或內容不对的错误。即使是用文本方式打开文本文件,也要谨慎使用,比如复制文件,就不应该使用文本方式。

  要特別注意的是,上面这样的说法仅适用于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语言开发者添了这样一个小小的麻烦。

### 文本模式与二进制模式打开文件区别及适用场景 #### 区别 在 C 其他编程语言中,文件可以通过两种主要模式打开文本模式二进制模式。 1. **文本模式** 当以文本模式打开文件时,文件的内容会被视为一系列字符,并可能经历某些平台特定的转换。例如,在 Windows 平台上,换行符 `\n` 可能会被自动替换为回车换行组合 `\r\n` 或反之亦然[^1]。这种行为使得文本模式适合于处理纯文本文件,因为这些转换有助于跨不同操作系统保持一致性。然而,对于非文本数据(如图片、音频或其他二进制格式),这样的转换可能会破坏原始数据结构。 2. **二进制模式** 使用二进制模式打开文件意味着不会对文件内容执行任何特殊处理或转换。所有的字节都会按原样读取或写入磁盘[^5]。因此,当需要精确控制数据传输或者正在处理的是非文本类型的文件(比如图像、视频或者其他任何形式的二进制对象)时,应该采用此模式来避免不必要的修改。 #### 用法示例 以下是分别展示如何在 C 中使用这两种模式的例子: ##### 文本模式下的文件操作 (C) ```c #include <stdio.h> int main() { FILE *file; char buffer[100]; file = fopen("example.txt", "rt"); // 't' 表明这是文本模式,默认情况下也可以省略't' if(file != NULL){ while(fgets(buffer, sizeof(buffer), file)){ printf("%s", buffer); } fclose(file); }else{ perror("Error opening file"); } return 0; } ``` 上述代码片段演示了怎样以只读的方式打开名为 `example.txt` 的文本文件并逐行打印其内容至标准输出设备[^4]。 ##### 二进制模式下的文件操作 (C/C++) 下面是一个简单的例子说明如何创建一个新的二进制文件并将整型数组保存进去: ```cpp #include <fstream> using namespace std; int main(){ int data[] = {1, 2, 3}; ofstream outFile("data.bin", ios::out | ios::binary); if(outFile.is_open()){ outFile.write(reinterpret_cast<char*>(data), sizeof(data)); outFile.close(); } else { cout << "Unable to open file"; } return 0; } ``` 这里我们利用 C++ 的 fstream 库函数实现了向新建立的二进制文件 “data.bin” 写入三个连续存储单元的过程[^3]。 #### 适用场景分析 - 如果目标是对常规的人类可阅读材料进行基本的操作——像编辑器程序那样加载文档或将日志记录到硬盘上,则应优先考虑运用文本模式。 - 对于那些涉及多媒体资源管理的任务或者是涉及到序列化复杂的数据结构的应用场合而言,由于它们往往依赖确切无误地复制位串的能力,所以更倾向于选用二进制模式来进行相应的 I/O 处理工作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值