一、FileStream对象
FileStream对象表示在磁盘或网络路径上指向文件的流。当类提供向文件读写字节的方法时,经常使用StreamReader或StreamWriter执行这些功能。这是因为Stream类操作字符数据。而FileStream类操作字节和字节数组。字符数据易于使用,但是有些操作比如随机文件访问,就必须由FileStream对象执行。
FileStream对象的构造函数:
FileStream aFile = newFileStream(“Log.txt”,FileMode.OpenOrCreate);
FileMode枚举具有几种成员:
Append------如果文件存在,就打开文件,将文件位置移动到文件的末尾,并创建一个新文件。FileMode.Append仅可以与枚举FileAccess.Write联合使用
Create------创建新文件;如果存在这样的文件,就破坏它。
CreateNew------创建新文件,但是如果已经存在此文件,则抛出异常
Open------打开现有的文件,但是不存在所指定的文件,则抛出异常
OpenOrCreate------如果文件存在,则规定打开文件,否则就创建新文件,如果文件已经存在,则保留在文件中的数据
Truncate------打开现有文件,清除其内容,然后我们可以向文件写入全新的数据,但是保留文件的初始创建日期,
必须存在有文件,否则就抛出异常
访问级别
前面的构造函数默认以只读模式打开文件,需要一个附加参数规定不同的访问级别,此参数是FileAccess参数。
FileStream aFile=new FileStream(”Log.txt”,fileMode.OpenOrCreate,FileAccess.Write)
FileAccess枚举有三种类型:Read、Write、ReadWrite.此属性的作用是:基于用户的身份验证级别改变用户对文件的访问
读取文件的位置用seek:public long Seek(long offset,SeekOrigin origin)
Long offset是规定文件指针以字节为单位的移动距离;
SeekOriginorigin是规定开始计算的起始位置,此枚举包含3个值:Begin,Current和End。
例:aFile.Seek(8,SeekOrigin.Begin);//SeekOrigin.Begin指得是文件指针从文件的第一个字节起;而参数‘8‘指
得是移动到文件的第8个字节
例2:afile.Seek(2,SeekOrigin.Current)//在当前位置开始,再移动2个字节。
例3:aFile.Seek(-5,SeekOrigin.End)//在文件末端位置开始,倒数5个字节。
读取数据
使用FileStream类读取数据不像使用StreamReader和StreamWriter类读取数据那么容易,这是因为FileStream类只能处理原始字节(raw byey),这使得FileStream类可以用于任何数据文件,而不仅仅是文本文件,通过读取字节数据就可以读取类似图像和声音的文件。这种灵活性的代价是不能使用它直接读入字符串。而使用StreamWriter和StreaMeader类却可以这样处理,从是有几种转换类可以很容易地将字节数组转换为字符数组,或者进行相反的操作。
Read()方法是从FileStream对象所指向的文件访问数据的主要手段:
Public int Read(byte[] array,int offset, intcount)
第一个参数是被传输进来的字节数组,用以接受FileStream对象中的数据。
第二个参数是字节数组中开始写入数据的位置,它通常是0,表示从数组的开端的文件中向数组写数据。
最后一个参数是规定从文件中读出多少字节。
写入数据
写入数据的流程是先获取字节数组,再把字节数据转换为字符数组,然后把这个字符数组用Write()方法写入到文件中,当然在写入的过程中,可以确定在文件的什么位置写入,写多少字符等等。
文件读写的范例:
读取文件
using System; using System.Collections.Generic; using System.Text; using System.IO; namespace myFile { class Program { static void Main(string[] args) { byte[] byData = new byte[100];//建立一个FileStream要用的字节组 char[] charData = new char[100];//建立一个字符组 try { FileStream aFile = new FileStream("../../../../Data.txt",FileMode.Open);//实例化一个FileStream对象,用来操作data.txt文件,操作类型是 aFile.Seek(55,SeekOrigin.Begin);//把文件指针指向,从文件开始位置向前55位字节所指的字节 aFile.Read(byData, 0, 100);//读取FileStream对象所指的文件到字节数组里 } catch (IOException e) { Console.WriteLine("close"); return; } Decoder d = Encoding.UTF8.GetDecoder();// d.GetChars(byData, 0, byData.Length, charData,0);//将编码字节数组转换为字符数组 Console.WriteLine(charData); Console.ReadLine(); return; } } }
写入文件:
using System; using System.Collections.Generic; using System.Text; using System.IO; namespace myFile { class Program { static void Main(string[] args) { byte[] byData = new byte[100];//建立一个FileStream要用的字节组 char[] charData = new char[100];//建立一个字符组 try { FileStream aFile = new FileStream("../../../../Data.txt",FileMode.Open);//实例化一个FileStream对象,用来操作data.txt文件,操作类型是 charData = "我是谁?111?".ToCharArray();//将字符串内的字符复制到字符组里 aFile.Seek(0, SeekOrigin.End); Encoder el = Encoding.UTF8.GetEncoder();//编码器 el.GetBytes(charData, 0, charData.Length, byData, 0, true); aFile.Write(byData, 0, byData.Length); } catch (IOException e) { Console.WriteLine("close"); return; } } } }
二、StreamWriter对像
用FileWriter来随机读取文件是个好主意,而用StreamWriter可以直接把字符串写入文件中,它处理重要的转换和向FileStream对像写入工作。创建StreamWriter有很多方法:
FileStream aFile = newFileStream(“Log.txt”,FileMode.CreatcNew);
StreamWriter sw = new StreamWriter(aFile);
也可直接从文件中创建StreamWriter对象:
StreamWriter sw = new StreamWriter(“Log.txt”,true);
后面这个Boolean值规定是附加文件还是创建新文件,如果此值为false,则就创建一个新文件,或者截取现有文件并打开它。如果此值设置为true,则打开文件,保留原来的数据,如果找不到文件,则创建一个新文件。注意:当创建FileStream对象时,您无法得到选项的范围。除了使用Boolean值附加或创建新文件外,我们根本就无法像使用FileStream类时那样规定FileMode属性;而且,您也无法设置FileAccess属性.因此您总是具有对文件的读写特权,为了使用任何高级参数,您必须在FileStream构造函数中规定这些参数,然后在FileStream对象中创建StreamWriter。
例:
using System; using System.Collections.Generic; using System.Text; using System.IO; namespace StreamWriterFile { class Program { static void Main(string[] args) { try { FileStream aFile = new FileStream("data1.txt",FileMode.OpenOrCreate);//建立一个fileStream对象 StreamWriter sw = newStreamWriter(aFile);//用FileStream对像实例一个StreamWriter对象 sw.Write("first."); sw.WriteLine("hello world!!!");//写入字符串,方法WriteLine写入时后面跟一个换行符 sw.Write("This is a");//写入字符串,方法Write写入时没有换行符 sw.Write("string of characters."); sw.Close();//用完后必须关闭对像 } catch (IOException e) { Console.WriteLine(e.ToString()); } } } }
三、StreamReader对象
1.读取文件
输入流用于从外部源读取数据,在很多情况下,数据源可以是磁盘上的文件或网络的某些位置,任何可能发送数据的位置都可以是数据源,比如网络应用程序,web服务,甚至是控制台。StreamReader是一个通用类,可以用于任何流;StreamReader对象的创建方式非常类似于StreamWriter对象的创建方式。
StreamReader类有两个基本的方法read和readLine
Read()方法将流的下一个字符作为正整数值返回,如果到达了流的结尾处,则返回-1
ReadLing()方法是读取并返回一行字符,如果返回为空,那么就是到达了流的结尾。
ReadEnd()方法读小文件最好,它直接读取完整的文件并作为字符串返回。
例:
using System; using System.Collections.Generic; using System.Text; using System.IO; namespace StreamReaderTest { class Program { static void Main(string[] args) { string strLine; try { Console.Write("请输入文件路径及文件名:"); string mess = Console.ReadLine(); FileStream aFile = new FileStream(mess, FileMode.Open); StreamReader sr = newStreamReader(aFile);//用FileStream对象实例化一个StreamReader对象 //strLine = sr.ReadToEnd();//读取完整的文件,如果用这个方法,就可以不用下面的while循环 strLine = sr.ReadLine();// 读取一行字符并返回 while (strLine != null) { Console.WriteLine(strLine); strLine = sr.ReadLine(); } sr.Close(); Console.ReadLine(); } catch (IOException e) { Console.WriteLine("an IOexception has been thrown!"); Console.WriteLine(e.ToString()); return; } return; } } }
2.分隔文件
读取使用逗号分隔的文件,string类提供了一种称为Split()的方法,可以用于将字符串按照提供的分隔符分隔成字符组.
例:
using System; using System.Collections.Generic; using System.Text; using System.IO; namespace CommaValues { class Program { static void Main(string[] args) { while (true) { string strLine; string[] strArray; char[] charArray = new Char[] { ‘,‘ }; Console.Write("请输入文件内容以逗号分隔的文件路径及文件名:"); string name = Console.ReadLine(); try { FileStream aFile = new FileStream(name, FileMode.Open); StreamReader sr = new StreamReader(aFile); strLine = sr.ReadLine(); while (strLine != null) { strArray = strLine.Split(charArray); for (int x = 0; x <= strArray.GetUpperBound(0);x++) { Console.WriteLine(strArray[x].Trim()); } strLine = sr.ReadLine(); } sr.Close(); //Console.ReadLine(); } catch (IOException e) { Console.WriteLine(e.ToString()); return; } //return; } } } }
四、使用BinaryWriter和BinaryReader
最后研究的读取器/编写器组是BinaryReader和BinaryWriter,它们都从System.Object直接派生。这些类型可以让我们从基层流中以简洁的二进制格式读取或写入离散数据类型。BinaryWriter类型定义了一个多次重载的Write()方法,用于把数据类型写入基层的流。除了Write()方法,BinaryWriter还提供了另外一些成员让我们能获取或设置从Stream派生的类型,并且提供了随机数据访问的支持(如表16-9所示)。
BinaryWriter核心成员成 员及作 用
BaseStream----- 这个只读属性提供了BinaryWriter对象使用的基层流的访问
Close() ----- 这个方法关闭二进制流
Flush() ----- 这个方法刷新二进制流
Seek() ----- 这个方法设置当前流的位置
Write() ----- 这个方法将值写入当前流
BinaryReader核心成员
成 员及作用
BaseStream----- 这个只读属性提供了BinaryReader对象使用的基层流的访问
Close() ----- 这个方法关闭二进制阅读器
PeekChar()----- 这个方法返回下一个可用的字符,并且不改变指向当前字节或字符的指针位置
Read() ----- 读取给定的字节或字符,并把它们存入数组
ReadXXX()
BinaryReader类定义了许多ReadXXX()方法来从流中获取下一个类型(ReadBoolean()、ReadByte()、ReadInt32()等)
下面的示例新建了一个*.dat文件并且写入了一些数据类型:
static void Main(string[] args) { // 为文件打开一个二进制编写器。 FileInfo f = new FileInfo("BinFile.dat"); BinaryWriter bw = new BinaryWriter(f.OpenWrite()); // 输出类型的BaseStream(在这里是System.IO.FileStream)。 Console.WriteLine("Base stream is: {0}", bw.BaseStream); // 在文件中存储一些数据。 double aDouble = 1234.67; int anInt = 34567; char[] aCharArray = { ‘A‘, ‘B‘, ‘C‘ }; // 写数据。 bw.Write(aDouble); bw.Write(anInt); bw.Write(aCharArray); bw.Close(); }
注意,从FileInfo.OpenWrite()返回的FileStream对象被传到BinaryWriter类型的构造函数中。使用这项技术就能很方便地在写入数据前引入一个流。需要理解的是,BinaryWriter构造函数能接受任何派生自Stream类型的参数(比如FileStream、MemoryStream或BufferedStream)。因此,如果希望向内存写二进制信息的话,只需提供一个MemoryStream对象即可。
BinaryReader类型提供了很多选项来从BinFile.dat文件读取数据。在这里,我们会使用PeekChar()来检测流中是否仍有可提供的数据,如果有的话,使用ReadByte()来取值。注意,我们用十六进制来格式化这些字节,并且在它们中间插入7个空格:
static void Main(string[] args) { // 为文件打开一个二进制编写器。 FileInfo f = new FileInfo("BinFile.dat"); ... // 以原始字节形式读取数据。 BinaryReader br = new BinaryReader(f.OpenRead()); int temp = 0; while (br.PeekChar() != -1) { Console.Write("{0,7:x} ", br.ReadByte()); if (++temp == 4) { // 每4个字节一行。 Console.WriteLine(); temp = 0; } } Console.WriteLine(); }