FileStream类是从抽象类Stream继承而来的,因此重写了Stream类的所有抽象的方法,比较重要的有Read(),Write(),Seek()。值得注意的是,FileStream是对字节进行操作的,区别于StreamWriter与StreamReader是对Unicode字符进行的。这可以从Write与Read方法的原型看出来:
public override int Read (
[InAttribute] [OutAttribute] byte[] array,
int offset,
int count
)
public override void Write (
byte[] array,
int offset,
int count
)
它们的第一个参数均是byte型的数据缓存器,是对字节流进行操作的。offset参数表示在数组中的偏移,count指从此位置需要操作的字节数目。
Write与Read是对一定数目的字节进行读取或者写入的函数,如果是单个字节,还有配套的ReadByte(),WriteByte()方法。
它们的原型是:
public override int ReadByte ()
public override void WriteByte (
byte value
)
这里需要注意的是,ReadByte()返回值是Int32型的,如果到了文件流末尾,那么返回-1。
关于Seek()方法,它是对文件流进行定位的。函数原型是:
public override long Seek (
long offset,
SeekOrigin origin
)
SeekOrigin是一个枚举类型,
成员名称 | 说明 | |
---|---|---|
Begin | 指定流的开头。 | |
Current | 指定流内的当前位置。 | |
End | 指定流的结尾。 |
Seek()的第一个参数表示偏移量,均指从起点开始,往后面进行偏移,第二个参数表示起点,例如:
Seek(10,SeekOrigin.End):从文件流末尾向后偏移10个字节。下面来分析这段程序:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace 文件操作
{
class Program
{
static void Main(string[] args)
{
using(FileStream fs=new FileStream("lena.raw",FileMode.Create,FileAccess.ReadWrite))
{
byte[] bt=new byte[10]{1,2,3,4,5,6,7,8,9,10};
fs.Write(bt, 0, 10);
// Console.WriteLine(fs.Seek(2, SeekOrigin.End));
Console.WriteLine(fs.Seek(0, SeekOrigin.Begin));
for (int i = 0; i < 10; i++)
{
Console.WriteLine(fs.ReadByte());
}
}
}
}
}
以Creat的方式打开文件,每次会重新覆盖原有的文件,类似C语言中的fopen( ,"wb")。这里有一个细节,如果不写 Console.WriteLine(fs.Seek(0, SeekOrigin.Begin));将当前位置指向文件的开头的话,后续读的字节打印出来是-1,这就说明了,执行完Write后,文件流指向了文件的末尾。
PS:根据实验结果证明,Write,WriteByte,Read,ReadByte均会使文件流的当前位置发生改变。
附加文件不同的FileMode的不同打开方式:
FileMode枚举成员,使用每个值会发生什么,取决于指定的文件名是否表示已有的文件。
成 员 |
文 件 存 在 |
文件不存在 |
Append |
打开文件,流指向文件的末尾,只能与枚举FileAccess.Write联合使用 |
创建一个新文件。只能与枚举FileAccess.Write联合使用 |
Create |
删除该文件,然后创建新文件 |
创建新文件 |
CreateNew |
抛出异常 |
创建新文件 |
Open |
打开现有的文件,流指向文件的开头 |
抛出异常 |
OpenOrCreate |
打开文件,流指向文件的开头 |
创建新文件 |
Truncate |
打开现有文件,清除其内容。流指向文件的开头,保留文件的初始创建日期 |
抛出异常 |