文件类型和流

来源:互联网 发布:php 数组合并 覆盖 编辑:程序博客网 时间:2024/04/27 09:40

正如wolfsecond(自己很敬佩的一个同学)所说,每个人要有承认自己无知的勇气,这对程序员的灵魂是有好处的(不知道这句话是不是他的原创,但确实是我们每个人都应当努力做到的)。计算机的领域是如此之广,也许我们每个人一生也就只限在自己那狭小的领域之内,肯于向别人,甚至那些在很多方面远不如你的人学习是需要勇气的。

很久以来就一直渴望有这样的一个环境,身边的人比自己都强很多,我想在这样的环境中自己的进步肯定是神速的。现实是我们自己可能很难有这样的机会,那么我们就更应该像自己身边每个人学习,也许只是某一个工具的某一个简单使用技巧。

前些天自己看了一些c++文件操作方面的东西,也算是做一个简单的总结吧,很多东西也都是自己的一些理解,有可能还不是很正确。很多东西可能比较简单,但学习、体会也是一点点慢慢积累的呀。

1.文件类型

一般将文件分为两种类型:文本文件(ASCII码文件)和二进制文件。

有一句话说的好:文本文件是一种特殊的二进制文件。不管是文本文件还是二进制文件在存储形式上都是以字节为单位的(一个字节一个字节,我们常说的流也就是这种字节流),每个字节都是8位的,这样共有0X00~0XFF共256种形式,文本文件只能使用其中的128种形式(也就是从00000000~01111111,也就是128个ASCII码,后面的128个扩展码不能用),而二进制文件则能使用这256种形式(00000000~11111111)。很多文件比如:图片文件、声音文件等之所以选择以二进制形式存储一个重要原因就是可以使用这256种形式,而不仅仅是128种形式。现在你能体会到文本文件是一种特殊的二进制文件了吧。

这里再说一点关于这两种文件的区别:比如数字128在文本文件中存储的是'1' '2' '8'这三个数字的ASCII码,也就是用3个字节,而在二进制文件中就用10000000这么一个字节,从这里能看出,二进制文件有时候更能节省空间。而对于abc来说,两者存储的应该是一样,都是三个字节。

上面很多内容也是参考这篇文章的:http://www.cs.umd.edu/class/spring2003/cmsc311/Notes/BitOp/asciiBin.html

2.c++对于文件的操作

这里先说一点:在windows平台下的文本文件'/n'换行符实际上是两个字符'/r'和'/n'(回车和换行),这两个字符没有什么特别的意义,只是表示这一行结束了,就像字符串'abc'在存储上的最后一个字符'0X00'也只是表示这个字符串结束了,没有实际的意义,在Unix平台下文本文件换行只用'/n'一个字符。而二进制文件不管在什么平台下都只是一个'/n'换行符。

对于一个文件,当我们用二进制方式打开(ios::binary)还是文本文件方式打开(默认方式),我想有区别的只是在对于换行的处理上,而具体的文件读写还是以字节为单位,所读的内容与文件存储形式一致.如果用二进制方式打开文件进行读写,则所读写的和其在内存中存储的完全一致,如果用文本文件方式进行读写,系统会将换行符'/r/n'(0x0D 0x0A)全部转换成单个的'/n'(0x0A),相应的写将'/n'(0x0A) 扩展为两个字节'/r/n'(0x0D 0x0A)  下面是我做的一个测试:
建议一个文件test.txt
abcd
efgh
ijkl
mnop
qrst
uvwx
yz
file.open("test.txt");       //以文本文件方式打开test.txt文件
file.open("test.txt,ios::binary");       //以二进制方式打开test.txt文件
int byteNumber = 0;
char ch;   
while(!file.eof())
{
    file.get(ch);
    byteNumber++;       
}
当我们用文本文件方式读时,所读总的字节数的是:33('/r/n'被处理成一个'/n'后进行读)
当我们用二进制方式读时,所读总的字节数是:39('/r/n'被当作两个字符进行读)
文件的结束符都是一个字符

 

3.c++文件操作的一些特点

<1>.类型安全: c中的print和scanf很多错误在编译期间无法检测,运行时才能检测(运行时才能决定参数的个数和对应的类型),c++则避免了这一问题

<2>.支持用户自定义的数据类型:c中只支持基本类型,c++中通过重裁运算符>> <<可以输入输出用户自定义类型

<3>.简单易用:感觉比使用print和scanf更方便些

<4>.效率相对较低:因为c++中的输入输出通过类来实现,在效率上不如c

4.流概念的一些体会

就像前面说的:流主要是指数据是以字节流的方式表现出来。c++中将流分为三类:标准输入输出流(键盘、显示器)、文件流和缓冲流。

我理解流就是一种数据的来源和去向:只要能提供数据的来源我们都能称其为流,比如数据来自键盘(标准输入流)、来自文件(文件流),来自内存的某一块缓冲(缓冲流);只要能作为数据去向的地方都能成为输出流,比如:显示器(标准输出流)、写入文件(文件流)、写入缓存(缓冲流).之前还听过socket流、管道流等,觉得c++怎么只抽象了这三类流,我想大概是因为。socket流等的数据来源或者去向本质上还可以归为这三类。就像socket流主要用于两台机器的通讯,数据来源于其中某一台机器,可是再具体些,这台机器上的数据终究要来自这三种抽象出来的流之一。

了解了流的概念后,我们就好理解流的重定向了。流的重定向主要是指我们将一种流的输入导入到另一种流的输出,或者将一种流的输出定位为另一种流的输入,这个在实际中好像经常遇到
下面是c++中的一个文件复制函数片断:
file1.open("test1.txt",ios::in);
file2.open("test2.txt",ios::out);
file2<<file1.rdbuf()这个函数具体信息大家可以自己查一下,大意是:我们知道打开文件test1.txt时,首先要将文件加载进内存的一个缓冲区中,通过file1.rdbuf()返回文件在内存的相应缓冲流(一组字节流),然后将这个流定位为文件test2.txt的输出,完成文件复制.

关于流重定向的另一个应用:自己以前看了一两个简单的后门、木马程序,程序大致实现如下
比如一个基于C/S的木马程序,服务端程序(也就是目标主机,感染木马的那台机器)可以在一个端口等待连接,一但客户端成功连接过来后,服务端程序就运行本机的cmd.exe程序,也就是windows下的控制台,等待客户端的传送的命令,并且将该命令重定向到控制台的输入,同时还可以将控制台的输出重定向给客户端,从而客户端就实现了远程控制。比如客户端通过输入"net user test 1234 /add"就可以在服务器上建立一个用户为test 密码为1234的帐户。

这篇文章自己主要总结了一下文本文件和二进制文件的一写区别,以及自己对于流概念的一些理解,可能有些地方还不是很正确.

原创粉丝点击