binary和text方式打开文件的区别

转载 2007年09月14日 14:38:00
binary和text方式打开文件的区别
 
 
发信人: LosComet (水母第3不厚道男), 信区: CProgramming
标  题: binary和text方式打开文件的区别
发信站: 水木社区 (Mon Apr  3 17:55:20 2006), 站内


这里并不是要说文本文件和二进制文件有什么区别,这两种文件之间的界限本来就很模糊
,事实上,把所有文件当成二进制文件就可以了。在这个层次上,一个文件和一块内存没
有什么区别,都是一个字节序列,一个字节就是一个介于0x00~0xFF之间的值

但是在Windows/DOS下,用fopen等函数打开文件的时候,最后一个参数里可以加上一个
"b"或者"t",用来告诉程序这个文件应该用什么方式打开。关于他们的区别,在MSDN上是
这样说的:

t
Open in text (translated) mode. In this mode, CTRL+Z is interpreted as an
end-of-file character on input. In files opened for reading/writing with "a+",
fopen checks for a CTRL+Z at the end of the file and removes it, if
possible. This is done because using fseek and ftell to move within a file
that ends with a CTRL+Z, may cause fseek to behave improperly near the end
of the file.  Also, in text mode, carriage return–linefeed combinations
are translated into single linefeeds on input, and linefeed characters are
translated to carriage return–linefeed combinations on output. When a
Unicode stream-I/O function operates in text mode (the default), the
source or destination stream is assumed to be a sequence of multibyte
characters. Therefore, the Unicode stream-input functions convert
multibyte characters to wide characters. For the same reason, the Unicode
stream-output functions convert wide characters to multibyte characters. 

b Open in binary (untranslated) mode; translations involving carriage-return
and linefeed characters are suppressed.  If t or b is not given in mode, the
default translation mode is defined by the global variable _fmode. If t or b
is prefixed to the argument, the function fails and returns NULL. 


为此,我做了如下的试验:

======================================================================
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void fwrite_test(){
        FILE * ft;
    FILE * fb;
    int i;
    unsigned char b;

    // 用两种模式打开两个文件写
    ft = fopen("t.txt", "wt");
    fb = fopen("b.txt", "wb");

    // 将0x00-0xFF写到两个文件中
    for(i = 0; i < 256; i++){
        b = (unsigned char)i;
        fwrite(&b, 1, 1, ft);
        fwrite(&b, 1, 1, fb);
    }

    fclose(ft);
    fclose(fb);
}

void fread_test(const char * filename){
    FILE * ft;
    FILE * fb;

    // 用来存储从文件中读出来的数据
    unsigned char buf_t[300] = {0};
    unsigned char buf_b[300] = {0};
    size_t cnt_t;
    size_t cnt_b;
    int i;

    // 用两种方式打开同一个文件读
    ft = fopen(filename, "rt");
    fb = fopen(filename, "rb");
    // 把数据分别读到buffer中,实际读取的字节数放到变量中
    cnt_t = fread(buf_t, 1, 300, ft); 
    cnt_b = fread(buf_b, 1, 300, fb);

    // 输出实际读取的字节数
    printf("t mode read:%d/nb mode read:%d/n", cnt_t, cnt_b);

    // 输出实际读取的内容
    printf("/nbuffer t:/n");
    for(i = 0; i < 300; i++){
        printf("%X : 0x%X/n", i,  buf_t[i]);
    }

    printf("/nbuffer b:/n");
    for(i = 0; i < 300; i++){
        printf("%X : 0x%X/n", i,  buf_b[i]);
    }

    fclose(ft);
    fclose(fb);
}

int main (int argc, char **argv)
{
    // 用两种方式写两个文件
    fwrite_test();

    // 用两种方式读取binary方式写入的文件
    fread_test("b.txt");
    printf("/n-------------------------------------/n"); // 分割线
    // 用两种方式读取text方式写入的文件
    fread_test("t.txt");
};

======================================================================

编译、运行上述代码,生成test.exe,然后运行:
test.exe > output.txt

这样会生成3个文件,b.txt、t.txt、result.txt

首先察看文件大小,b.txt是256字节、t.txt是257字节
然后用16进制编辑器(我用的WinHex)打开两个文件以对比
对比之后发现,b.txt是从00-ff的256个字节
而t.txt中,在0x09和0x0A之间多了一个字节,就是0x0D

然后看result.txt的内容:
首先是,读取那个用b方式生成的文件
用t方式打开的,只读取了26个字节
而用b方式打开的,完整地读取了256个字节

看看buffer中的内容,buf_t中,只有前26个自节有值,后面都是0
也就是说,从第27个字节(0x1A)开始,后面的都没有读取

然后找到分割线,继续看下面的内容,读取t.txt的内容,也就是用t方式生成的多一个
0x0D的那个文件

这个文件共有257字节,而用b方式打开之后也是读取了257字节
但是看看t方式打开之后,仍然是读取了26字节
看看buf_t里面的内容,仍然是从0x00-0x19的这26个字节


======================================================================
总结:
0x0A是字符"/n"(换行,有时被称为line feed、lf)、0x0D是字符"/r"(回车,carriage
return)、0x1A是什么呢?我用VIM打开一个有0x1A的文件看到的是^Z

在t方式打开文件的时候,写入一个0x0A,会被扩展为0x0D、0x0A,这个在以前的讨论中
说过,也就是把/n转化成/r/n,在t方式读取的时候,0x0D、0x0A会被当作只有一个0x0A。

Ctrl-Z就是在Windows下的控制台下输入EOF是要按的键,也就是说,在读取文件的时候
用t方式打开的话,会把0x1A当作是一个文件的结尾,也就是EOF,后面的内容将不会视为
该文件的内容。

而用b方式打开文件的时候,会原汁原味地交换内存和文件中的数据,没有任何转换。

在Windows下,如果不加b或者t,或者在C++里面不加ios::binary或ios::text
默认是按照t方式打开的文件(这个应该所使用的库有关,反正VC是这样的)
这一点要注意。

另外,我把刚才的程序拿到Linux下编译运行了一次,结果是b和t没有区别,表现出来的
行为和Windows下用b方式打开文件一样,0x0A、0x1A等数据进行特别处理。

贴上Linux下的部分man page的内容:

man fopen:
       The mode string can also include the letter  ``b''  either  as  a  last
       character  or  as a character between the characters in any of the two-
       character strings described above.  This is strictly for  compatibility
       with  ANSI  X3.159-1989  (``ANSI  C'')  and has no effect; the ``b'' is
       ignored on all POSIX conforming systems, including Linux.  (Other  sys-
       tems  may treat text files and binary files differently, and adding the
       ``b'' may be a good idea if you do I/O to a binary file and expect that
       your program may be ported to non-Unix environments.)

也就是说,Linux下b和t是没有区别的


windows/dos真麻烦^_^  ——某斑竹语
 

关于写回车换行到unicode文件的问题。

void AppendBufToFile(char* file_name,void* buf,U32 len) { FILE * fp = NULL; fp = fopen(file...
  • annkie
  • annkie
  • 2011年11月29日 14:34
  • 4195

Python文件操作之open()的mode

open的modemode can be: 'r' when the file will only be read, 只读, 'w' for only writing (an existing fil...
  • Tyronne
  • Tyronne
  • 2015年07月22日 17:13
  • 8083

C++作业:text格式与binary格式

fopen的打开模式中有text和binary两类,如"rt", "rb",但是在实际工程中,应该只使用binary格式,彻底忘记text模式。为什么呢?因为当以text方式来操作文件时,在windo...

binary和text方式打开文件的区别(转)

这个我原来也遇见过,并处理过以binary和text方式打开文件的区别,当时是05年实现发送http数据包,一直有问题,后来截取数据对比发现的,但是当时没有记录,今天发现这篇文章对这里进行了总结,故收...

fstream 几种打开文件的方式,方便以后用

fstream fout; //(1)以输出的方式打开文件,若文件不存在建立文件,若文件存在将文件长度置为0 fout.open("D:/1.txt",ofstream::out|ofstream::...

C++ fstream流的eof()函数多读一行的问题

C++ fstream流的eof()函数多读一行的问题。

MYSQL的binary解决mysql数据大小写敏感问题的方法|Blob与Text的区别-【mysql学习笔记】

MYSQL的binary解决mysql数据大小写敏感问题的方法|Blob与Text的区别 BINARY不是函数,是类型转换运算符,它用来强制它后面的字符串为一个二进制字符串,...

C++写文件的text模式和binary模式

最近发现一个bug。客户端接收服务器发送回的UTF-8编码的字符串后,明明正确转码为UTF-16 little endian,但是保存为文件时用记事本打开后就是乱码。后来检查代码,发现打开文件时使用的...

【计算机】二进制(Binary)与文本(ascii)传输方式区别

FTP可用多种格式传输文件,通常由系统决定,大多数系统(包括UNIX系统)只有两种模式:文本模式和二进制模式。文本传输器使用ASCII字符,并由回车键和换行符分开,而二进制不用转换或格式化就可传字符,...

python文件打开方式详解——a、a+、r+、w+区别

第一步 排除文件打开方式错误: r只读,r+读写,不创建 w新建只写,w+新建读写,二者都会将文件内容清零 (以w方式打开,不能读出。w+可读写) **w+与r+区别: r+:可读可写,若文...
  • HHTNAN
  • HHTNAN
  • 2017年06月14日 19:13
  • 336
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:binary和text方式打开文件的区别
举报原因:
原因补充:

(最多只允许输入30个字)