在C#中,读取,写入文件最基本的操作对象有FileStream,StreamReader,StreamWriter三种。这三种都是继承于抽象类Stream的流。流是一个很重要的概念,不仅仅局限于文件输入\输出,还能用来访问网络,内存地址和其他一些流相关的抽象设备。下面来说一下个人对流的一些理解。
一开始我对流的理解是这样的:文件读取最基本的流是二进制流(FileStream)——将二进制流转化为字节数组(byte[])(byte[] bts=FileStream.Read())——字节数组根据编码方式转码成字符串(Enconding.Default.ToString())——操作字符串。我在网上查了很多资料,对于二进制流和字节流的解释都很模糊,有些文章只说二进制流,有些文章只说字节流,更多的都统称为二进制字节流。对此我很迷惑。
然后多找了一些基础的书后,我发现二进制流这个概念是多余的。事实上传输的最基本单位是字节,文件存储的格式也是字节,字节流可以处理任意格式的数据,包括二进制数据。FileStream进行传输的也是字节流。这个是最根本的流。
字节流可以传输exe文件,图片文件,声音文件,但是字节流是没法直接将数据写入字符串,而在很多时候,要处理的是文本文件 ,所以有了个字符流的概念。 StreamReader,StreamWriter操作的便是字符流。所谓的字符流,可以简单理解为将字节流按照一定的编码方式(Encoding.GetEncoding("gb2312")等)编码而成的数据流。将字符流传输到操作系统后,由操作系统解码成相应的字节数组(是否由操作系统解码不得而知,只是个人理解)。
另外要注意的一点是,字符流是放在一个缓冲区内编码,再由这个缓冲区写入到文件中,而字节流是直接发送到文件中。这样的区别是,假如字符流不调用Close()、Flush()或Dispose()方法,数据只存在于内存中而不会写入文件中。这就是平时常说的要关闭文件的原因。
下面给两个例子说明字符流和字节流的区别。
/// <summary> /// 读取文件数据 /// </summary> /// <returns>返回得到的字符串</returns> static string ReadByteStream() { FileStream byteStream = File.OpenRead(@"D:\1.txt");//读取字节流对象 byte[] bts=new byte[byteStream.Length];//设置一个byte数组,长度为byteStream所包含的字节长度 byteStream.Read(bts,0,bts.Length);//将byteStream内的字节数据存入bts字节数组 string str = Encoding.Default.GetString(bts);//按默认编码方式将字节数组转换为字符串 byteStream.Close();//关闭字节流并且释放资源 return str; } /// <summary> /// 用字节流方式写入数据 /// </summary> /// <param name="str">要写入的数据</param> static void WriteByteStream(string str) { FileStream byteStream = File.OpenWrite(@"D:\1.txt");//获取字节流对象 byte[] bts = Encoding.Default.GetBytes(str);//按默认编码方式将字符串转换为字节数组 byteStream.Write(bts, 0, bts.Length);//将bts内的字节数据写入字节流,注意在这个过程中,数据已经写入文件D:\1.txt。 byteStream.Close();//关闭字节流并且释放资源 } /// <summary> /// 用字符流方式读取数据 /// </summary> /// <returns></returns> static string ReadCharStream() { StreamReader charStream =new StreamReader(@"D:\1.txt",Encoding.Default);//读取字符流对象,这一过程中已按照默认编码方式将字节流转换为字符流 string str = charStream.ReadToEnd();//读取所有字符,返回的是一个字符串 charStream.Close();//关闭字符流并且释放资源 return str; } /// <summary> /// 用字符流方式写入数据 /// </summary> /// <param name="str">要写入的数据,该字符串已默认使用Unicode编码<</param> static void WriteCharStream(string str) { StreamWriter charStream = new StreamWriter(@"D:\1.txt");//读取字符流对象,这里无法设置编码方式,编码方式是在形成字符串的地方,系统默认使用Unicode编码 charStream.Write(str);//注意这一步是将字符串写入内存中的缓冲区,并未真正传输到文件中。我的理解是这个流还在内存中。 charStream.Flush();//字符流发送到文件中。直接调用Close方法可以不需要这个方法。 charStream.Close();//关闭字节流并且释放资源 } //目前使用字节流和字符流都可以实现读写数据,但是这几个例子都是文本数据,假如不是文本数据,那么无法使用字符流 }