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真麻烦^_^  ——某斑竹语
 

Plain Binary (Flat-Form Binary) File

Plain Binary (Flat-Form Binary) File(C) 2004-11-1 Gr1x . All rights reserved.   So what does plain b...
  • gr1x
  • gr1x
  • 2004年11月01日 18:15
  • 1261

grep的时候Binary file (standard input) matches

grep 识别文件的时候,认为这个是个二进制文件,报告错误,
  • benbendy1984
  • benbendy1984
  • 2014年06月11日 10:01
  • 2549

C++中关于text file和binary file

    ASCII文件包含text文件和binary文件,只要这些文件的编码是ASCII字符集的。与binary文件相对的概念叫做“text文件”!关于下面这个问题:   在unix,linux等类u...
  • ToSoftWare
  • ToSoftWare
  • 2010年10月21日 09:22
  • 4059

grep的时候Binary file matches **.log 怎么解决

grep的时候Binary file matches  **.log 怎么解决 软件 分享到: 专业回答 2015-01-14 11:21 操...
  • xiayu98020214
  • xiayu98020214
  • 2015年10月12日 11:21
  • 4620

Linux 使用grep命令 遇到 Binary file matches **.log 解决方法

操作 grep "xxx" a.log 结果 Binary file a.log matches 原因:grep认为a.log是二进制文件 解决方法:grep -a "xxx" a....
  • wangyili002
  • wangyili002
  • 2016年08月22日 19:01
  • 1518

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

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

解决`Sublime Text` 不能被设置为默认打开方式

文章转载于:https://zhuanlan.zhihu.com/p/25756829最近碰到这样一个问题,由于卸载了旧版本的Sublime Text2,并且重新安装了的Sublime Text3包,...
  • u012569796
  • u012569796
  • 2017年08月21日 16:14
  • 1595

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

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

解析文本文件 "r" 与 "rb" 模式的区别(Python)

Difference between parsing a text file in r and rb mode0. EOL(End-Of-Line)区别主要在 EOL 的处理方式不同。对于不同的操作系...
  • lanchunhui
  • lanchunhui
  • 2017年02月19日 21:35
  • 2757

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
  • 10780
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:binary和text方式打开文件的区别
举报原因:
原因补充:

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