C#文件与流(FileStream、StreamWriter 、StreamReader 、File、FileInfo、Di,有需要的朋友可以参考下。 文件与流(FileStream、StreamWriter 、StreamReader 、File、FileInfo、Directory、DirectoryInfo、Path、Encoding) 10.1、FileStream 10.1.1、定义一个流对象 Streamfs =newFileStream(@"D:\FINISH.TXT",FileMode.Open,FileAccess.Read,FileShare.Read); 说明: Stream是父类,FileStream是子类,父类是一个抽象类,子类才是实现类。 FileMode是一个枚举类型,它有很多值: Open:表示该流对象应该打开现有文件,如果文件不存在,那么就会打开异常的。 CreateNew:表示创建新文件,如果文件存在,那么就会发生异常。 Create:表示创建新文件,如果文件存在,那么就会被改写(清空再写)。 OpenOrCreate:表示如果文件存在就打开,不存在就创建。 FileAccess:控制本流对文件的访问权限:读、写、读写。 FileShare:当前的流在对指定文件进行访问的时候,控制别的流对该文件的访问权限:读、写、读写、没有任何权限,默认情况下,外界是没有权限来访问该文件的,除非指定。 10.1.2、读取文件Streamfs =newFileStream(@"D:\FINISH.TXT",FileMode.Open); intlength = fs.Read(byte[] buffer,intoffset,intcount); buffer:这个是字节数组,是用来存放读取的文件的。 offset:这个是buffer中的相对于起始索引0的偏移量,也就是从offset开始存放的。 count:计划从流文件中读取的字节数,count不要去超越buffer的长度。 返回值:该函数返回从文件中实际读取字节数。0<=返回值<= count 注意: 对于Read函数,只要流没有关闭它所指向的文件,那么第一次读取是从第一个字节开始的,第二次读取从第一次读取的最后一个字节的下一个开始,有seek会自动的将流当前指向的文件的位置往后移动,以后的读取依次类推。 读取文件的时候,fs有一个Length属性,表示它所指向的文件的字节大小,即文件的总长度。 10.1.3、写入文件Streamfs =newFileStream(@"D:\FINISH.TXT",FileMode. Create); fs. Write(byte[] buffer,intoffset,intcount); buffer:这个是字节数组,就是将该字节数组中的数据写入到文件中的。 offset:这个是buffer中的相对于起始索引0的偏移量,也就是从offset开始读取buffer的。 count:从buffer中读取的字节数,写入到文件中,count <=buffer.length - offset。 返回值:该函数无返回值。 注意:对于Write函数,如果文件是已存在的,在第一次write之前,会将文件全部清空,然后只要流没有关闭它所指向的文件,那么第一次写入文件是从文件开头开始写入的,第二次写入是从第一次写入的最后一个字节的下一个开始,有seek会自动的将流当前指向的文件的位置往后移动,以后的写入依次类推。 这种写入只是写入到缓冲区中,文件中还没有,要想真的写入文件,还必须依赖下面的函数: fs.Flush(); 这个是将缓冲区的内容写入到基础流中,并清空缓冲区,这样才可以在文件中查看到内容。只要文件没有被关闭,就可以不停的Write和Flush,后面的写入是往文件末尾写。 如果缓冲区很大,可以Write一部分然后Flush一部分,分多次Write和Flush。 10.1.4、关闭文件fs. Close() 这个是将缓冲区的内容写入到基础流中,并清空缓冲区,所以即使没有Flush(),调用的时候,一样会完成Flush()的功能;并关闭流与它所指向的文件之间的联系,并释放所有的与之关联的资源。这样这个文件就与该流没有任何的关系了,可以继续被别的流来访问了。所以当流使用完毕之后一定要关闭。当流关闭之后,就不能再用之前的流对象来操作文件了,否则会出错。 10.2、字节与整数、浮点数、字符串的相互转换在读写文件的时候,经常涉及到数值与字节的相互转换、字符串与字节之间的相互转换,下面分别来说明: 10.2.1、32位整数与字节的相互转换byte[] buffer =BitConverter.GetBytes(inta); 这个是将32位的整数(我们看到的是十进制的整数,32位是指在计算机中以二进制存放的时候,占有32个bit位)转换成为长度为4的字节数组:32位整数表示的是二进制的32个bit位,正好对应着4个字节,在字节中,从低八位到高八位加起来正好也是32位,最低位是二的零次方,然后是二的一次方,依次类推,所以转换的时候,首先将十进制的32位整数按照二进制转换成32个bit位,然后按照八位进行分割,变成四个字节,分别存放到buffer中,整数的低八位存放在buffer[0],最高的八位存放在buffer[3]中,编译调试的时候,看到的每一个字节的数字又是单个字节从二进制转换成十进制的值。 inta =BitConverter.ToInt32(byte[] buffer,intstartIndex) 这个是将buffer中的,从startIndex开始的四个字节,按照从低八位到高八位的顺序转换成为32位的整数值,startIndex是低八位,startIndex + 3是高八位。 10.2.2、64位double与字节的相互转换byte[] buffer =BitConverter.GetBytes(doublea); 这个是将64位的double转换成为长度为8的字节数组,double的低八位存放在buffer[0],最高的八位存放在buffer[7]中。 doublea =BitConverter. ToDouble(byte[] buffer,intstartIndex) 这个是将buffer中的,从startIndex开始的八个字节,按照从低八位到高八位的顺序转换成为64位的double值。 10.2.3、字符串与字节的相互转换byte[] buffer =Encoding.Default.GetBytes(stringa); 这个是将一个字符串转换成为一个字节数组。 strings =Encoding.Default.GetString(byte[] buffer,intstartIndex,intcount); 这个是将buffer数组转换成为字符串,startIndex是buffer中的起始索引,count是buffer中的要转换的字节长度。 10.3、StreamWriter、StreamReader在读写文件的时候,经常要读写文本文件,在读写文本文件的时候有两个类是非常方便的。 10.3.1、写文本文件StreamWritersw =newStreamWriter(@"D:\test.txt"); 定义了一个StreamWriter对象之后,首先是没有文件就创建文件,有就把文件内容清空(本节中的构造函数是这样的,但是可以调用其他的重载构造函数来完成不同的功能)。 sw.WriteLine("123"); 这个函数是将一个字符串写入到文件的末尾,并且自动的加上\r\n换行。 sw.Write("123"); 这个是将一个字符串写入到文件的末尾,不会加\r\n换行。 注意:以上的两个函数只是写入到缓冲区了,但是此时去查看文件,文件还是没有被写入的。 sw.Flush(); 这个是将缓冲区的内容写入到基础流中,并清空缓冲区,这样才可以在文件中查看到内容。只要文件没有被关闭,就可以不停的Write和Flush,后面的写入是往文件末尾写。 如果缓冲区很大,可以Write一部分然后Flush一部分,分多次Write和Flush。 sw. Close() 这个是将缓冲区的内容写入到基础流中,并清空缓冲区,所以即使没有Flush(),调用的时候,一样会完成Flush()的功能;并关闭流与它所指向的文件之间的联系,并释放所有的与之关联的资源。这样这个文件就与该流没有任何的关系了,可以继续被别的流来访问了。所以当流使用完毕之后一定要关闭。当流关闭之后,就不能再用之前的流对象来操作文件了,否则会出错。 10.3.2、读文本文件StreamReadersr =newStreamReader(@"D:\test.txt",Encoding.Default); stringstr = sr.ReadLine(); 这个函数是读取文本文件中的某一行,并将该行后面的\r\n删除掉,返回字符串,如果该行后面没有\r\n,那么就直接返回该行。读取总是从上一次读取之后再读取,如果读完了所有的行,再次读取就会返回null了。 stringstr = sr.ReadToEnd(); 读取整个文本文件的,以字符串的形式返回。 注意:最后操作完成后要关闭流。文件如果不存在,那么就会在定义的时候异常。 10.4、File该类是一个与文件有关的类,是一个静态类,它里面的函数是静态函数。主要提供了对文件的创建、删除、移动、打开文件的静态方法。 10.4.1、文件拷贝File.Copy(stringsourceFileName,stringdestFileName) 两个参数包含完整的路径和文件名,目标路径中不能有与destFileName同名文件,否则会异常。 File.Copy(stringsourceFileName,stringdestFileName,booloverwrite) 前两个参数包含完整的路径和文件名,最后一个参数指示如果在目标路径中有同名文件,是否覆盖这个文件。 10.4.2、判断文件是否存在File.Exists(stringpath); boolisExist =File.Exists(@"c:\zwj"); 如果path指定的文件还存在,那么就返回true,否则返回false 10.4.3、删除文件File.Delete(stringpath); 删除path指定的文件。如果存在就删除,不存在也不会引发异常。 10.4.4、文件移动File.Move(stringsourceFileName,stringdestFileName) 两个参数包含完整的路径和文件名,目标路径中不能有与destFileName同名文件,否则会异常。 10.4.5、创建文件File.Create(stringpath); 如果文件不存在,那么就创建;如果存在,且为可写,那么就覆盖;如果存在不可写,那么就会发生异常。 默认情况下,新创建的文件是可读写的。 10.4.6、与文件有关的几个时间File.GetCreationTime(stringpath); 这个函数是获取文件的创建时间,返回DateTime。 File.GetLastAccessTime(stringpath); 这个函数是获取最后一次访问文件的时间,返回DateTime。 File.GetLastWriteTime(stringpath); 这个函数是获取文件的最后一次的修改时间,返回DateTime。 10.5、FileInfo类该类也是一个与文件有关的类,但是该类不是一个静态类,该类必须经过实例化之后才可以使用。 FileInfofi =newFileInfo(stringfileName); 10.5.1、复制fi.CopyTo(stringdestFileName) 目标路径中不能有与destFileName同名文件,否则会异常。 fi.CopyTo(stringdestFileName,booloverwrite) 最后一个参数指示如果在目标路径中有同名文件,是否覆盖这个文件。 注意:以上两个函数会返回FileInfo对象,这个对象是指向destFileName的。 10.5.2、删除fi.Delete(); 永久删除文件,文件不存在也不会发生异常。 10.5.3、移动fi.MoveTo(stringdestFileName) 目标路径中不能有与destFileName同名文件,否则会异常。 10.5.4、属性d:\programmfile\zwj.txt 1、 CreationTime:获取或者设置文件的创建时间。返回DateTime。 2、 LastWriteTime:最后一次的修改时间。返回DateTime。 3、 LastAcessTime:最后一次的访问时间。返回DateTime。 4、 DirectoryName:获取包含该文件的目录的完整路径的字符串:d:\programmfile 5、 FullName:获取包括文件名的完整路径:d:\programmfile\zwj.txt 6、 Name:获取文件名和扩展名:zwj.txt 7、 Extension:获取文件的扩展名:.txt 8、 Exists:指示文件是否存在,存在返回true,否则为false。 9、 IsReadOnly:获取或者设置当前的文件是否为只读的。是返回true,否则为false。 10、Length:返回文件的长度,以字节为单位。长整型。 11、Directory:获取包含该文件的目录的DirectoryInfo实例。 10.6、关于文件的总结1、不论是创建文件还是读取文件,只要文件的路径只是一个文件名,而没有绝对的路径,那么文件名默认为当前目录下面。这个当前是可能在变化的,程序开始启动的时候,当前肯定是exe同一级目录下面,但是有时候程序启动之后,再进行某些操作的时候,比如导出到excle报表,选择了别的文件夹路径,那么这个当前路径就是新路径而非exe同一级目录了。 2、..\:这个表示当前目录的上一级目录。这个当前目录像上面一样也是可能变化的。 3、当对一个文件第一次进行写操作的时候,首先会把文件的内容清空。 4、如果要想找到一个固定的exe文件的路径: Application.ExecutablePath:获取启动应用程序可执行文件的路径,包括可执行文件的名称: E: \source\存储过程版\PVPT\MainMenu\bin\Debug\MainMenu.EXE Application.StartupPath:获取启动应用程序可执行文件的路径,不包括可执行文件的名称: E: \source\存储过程版\PVPT\MainMenu\bin\Debug(没\) 10.7、Directory该类是一个与目录有关的类,是一个静态类,它里面包含了静态函数和静态属性。 1、 创建目录 Directory.CreateDirectory(stringpath); 按照path所指定的路径去创建目录、子目录,返回一个指向path的DirectoryInfo对象。这里是创建目录而非文件,不能通过"r:"创建一个逻辑盘,只能在现有的逻辑盘下面创建目录。重复创建已经存在的目录是不会发生异常的。任何新创建的目录名不能与该目录同一级目录下的文件名同名,否则就会报错。 2、 删除目录 Directory.Delete(stringpath); 这个函数是删除目录,这个目录必须为空目录,即里面不能有目录和文件。否则异常。目录不存在也会异常。 Directory.Delete(stringpath,boolrecursive); 这个函数是删除目录,当recursive为true,那么可以删除非空目录,否则只能删除空目录。目录不存在也会异常。 3、 移动目录 VoidDirectory.Move(stringsourceDirName,stringdestDirName) 将原目录的内容全部移到目标目录里面,然后将原目录删除。 4、 判断目录是否存在 Directory.Exists(stringpath); 存在返回true,否则返回false。 5、 得到目录的创建时间:DateTime Directory.GetCreationTime(stringpath); 6、 得到目录的最后一次访问时间:DateTime Directory.GetLastAccessTime(stringpath) 7、 得到目录的最后一次修改时间:DateTime Directory.GetLastWriteTime(stringpath) 8、 得到当前的执行程序所在的目录:stringDirectory.GetCurrentDirectory(stringpath); 9、string[]Directory.GetDirectories(stringpath); 获取指定目录中的子目录名称,只是获取指定目录的下一级,而非下两级或者下三级。返回的是包括目录名在内的完整的路径字符串数组。 10、string[]Directory.GetFiles(stringpath); 获取指定目录中的子文件名称,只是获取指定目录的下一级,而非下两级或者下三级。返回的是包括文件名在内的完整的路径字符串数组。 11、stringDirectory.GetDirectoryRoot(stringpath) 获取path执行的路径的根目录,卷信息,比如”d:\”,path可以是文件或者目录 12、string[]Directory.GetLogicalDrives(); 得到本系统的逻辑盘,以字符串的形式返回。如:”d:\” 13、DirectoryInfoDirectory.GetParent(stringpath); 14、 得到指定的path的父目录,返回DirectoryInfo对象,path可以是文件和目录。如果path是根目录,那么就返回null。 注意:目录最后不要加”\” 10.8、DirectoryInfo类该类也是一个与目录有关的类,但是该类不是一个静态类,该类必须经过实例化之后才可以使用。 DirectoryInfodi =newDirectoryInfo(@"d:\Program Files"); 10.8.1、属性1、CreationTime:获取或者设置目录的创建时间。返回DateTime。 2、LastWriteTime:最后一次的修改时间。返回 DateTime。 3、LastAcessTime:最后一次的访问时间。返回 DateTime。 4、Exists:指示目录是否存在,存在返回true,否则为false。 5、FullName:获取目录的完整路径,返回string。 6、Extension:获取目录名的扩展名,返回string。 7、Name:不包含路径的目录名,即文件夹的名字,返回string。 8、Parent:获取父目录,如果当前目录是根目录,就返回null,否则返回DirectoryInfo。 9、Root:获取当前目录的根目录,返回DirectoryInfo。 10.8.2、方法1、DirectoryInfodi.CreateSubdirectory(stringpath) 这个是在当前目录的下面创建子目录、子子目录,返回一个新的DirectoryInfo对象。比如path:a\b\c,a前面不能有\。 2、voiddi.Delete() 这个表示删除di指定的空目录,如果目录中有内容,那么会引发异常。 voiddi.Delete(bool) 如果目录不为空,那么true表示全部删除,false表示不删除。如果目录为空,不论true还是false都将直接删除。 3、DirectoryInfo []di.GetDirectories(); 返回当前目录的下一级所有子目录。如果没有,返回的数组长度为0. 4、FileInfo[]di.GetFiles(); 返回当前目录的下一级所有子文件。如果没有,返回的数组长度为0. 10.9、Path该类是一个与路径相关的类,是一个处理路径字符串的,它不会去识别文件或者目录,它只会去识别字符串,然后单纯的按照字符串来处理,它里面的函数全部是public static。 1、Path.ChangeExtension(stringpath,stringextension); 这个函数是用来更新扩展名的,path为完整的路径,extension是含有签到句点的扩展名。如果path没有扩展名,那么就加上extension,有就直接更新。如果extension为null或者空字符串,那么会将path中的扩展名去掉。这个只是对字符串进行变换,对原文件不会有任何的影响。 2、Path.GetDirectoryName(stringpath); path为文件或者目录的路径,这个是返回文件或者目录的上一级目录,即返回的是最后一个”\”符号之前的字符串,如果path为null或者为根目录,那么就返回null。 3、Path.GetExtension(stringpath); 返回指定路径的带前导句点的扩展名。如果没有扩展名,就返回长度为0的字符串。如果path为null就返回null。 4、Path.GetFileName(stringpath); 获取包括扩展名在内的文件名,如果是目录,也会当成文件处理。path如果为根目录则返回长度为0的字符串;如果为null则返回null。 1、Path.GetFileNameWithoutExtension(stringpath); 获取不包括扩展名在内的文件名,如果是目录,也会当成文件处理。path如果为根目录则返回长度为0的字符串;如果为null则返回null。 2、Path.GetFullPath(stringpath); path为相对路径或者绝对路径,返回绝对路径。 3、Path.GetPathRoot(stringpath) 获取path的根目录信息,如果如果path为null,那么就返回null。 10.10、小结注意:任何一个文件都有三个时间: 创建时间:这个文件的创建时间,如果把这个文件复制到另外一个路径下面,那么文件的创建时间就发生了变化,是复制时的时间;如果对这个文件改名,那么创建时间不会发生改变。 最后一次的修改时间:这个时间指的是最后一次修改文件内容的时间。如果把这个文件复制到另外一个路径下面,那么文件的最后一次修改时间就不会发生变化;如果对这个文件改名,那么最后一次修改时间也不会发生改变。只有修改内容才会发生变化。 最后一次的访问时间:是最后一次访问这个文件的时间,这个时间比较模糊。 如果用一个文件A去覆盖同名文件B,那么B被覆盖后,B的创建时间不变,最后一次的修改时间变成了A的最后一次修改时间。最后一次修改一个文件的时候,如果不保存,那么修改时间还是原来的时间。 |
|