这节讲一下使用FileStream读写数据,这是一个比较基础的流。
FileStream类只能处理原始字节,所以它可以处理任何类型的文件。
先看一下它的构造方法:
代码语言:javascript复制FileStream fs = new FileStream("./demo.txt", FileMode.Open, FileAccess.Read);
这个方法最少有两个参数,也就是前两个,第一个是文件路径,第二个FileMode枚举,规定文件的打开方式,是正常打开还是创建等等,第三个是FileAccess枚举,规定流的访问形式,是写入还是读取等等,不指明这个参数,它的默认值是ReadWrite,也就是可读可写。
FileMode枚举成员:
成员 | 访问的文件存在 | 文件不存在 |
---|---|---|
Append | 从文件最后追加数据,只能与FileAccess.Write使用 | 创建新文件,只能与FileAccess.Write使用 |
Create | 删除原文件,创建新文件 | 创建新文件 |
CreateNew | 抛出异常 | 创建新文件 |
Open | 从文件开头写入数据 | 抛出异常 |
OpenOrCreate | 从文件开头写入数据 | 创建新文件 |
Truncate | 清除文件内容,从开头写入数据,保留文件初始创建日期 | 抛出异常 |
FileAccess枚举成员:
成员 | 作用 |
---|---|
Read | 打开文件,只读 |
Write | 打开文件,只写 |
ReadWrite | 可读可写 |
File和FileInfo类都提供了OpenRead()和OpenWrite()这两个方法,可以快速创建只读或者只写的FileStream对象。
读写文件:
读取文件,需要用到Read()和Write(),这两个方法最常用的重载如下所示:
代码语言:javascript复制len=fs.Read(buffer, 0, buffer.Length)
write.Write(buffer, 0, len)
buffer是一个字节数组,用于存放一次读取的字节,可以自定义大小;第二个参数是偏移量,指示从buffer的第几个索引开始读,一般都是0,从开始读取;第三个参数是一次读取的大小,这个一般也都是固定的,是数组的长度。Read()方法的返回值是本次读取实际读取的长度,因为存在最后一次读取的长度不满buffer的长度的情况,Write()方法,第三个参数是指定写入的长度,这里一般指定Read()方法的返回值,这样就不会出现将多余的无关数据写入文件中。
下面看一下例子:
代码语言:javascript复制//读取数据并展示
FileStream fs = new FileStream("./demo.txt", FileMode.Open, FileAccess.Read);
int len, i = 0;
//存放每次读取的数据
byte[] buffer = new byte[5];
//存放所有读到的数据,最后将其转换为字符串
byte[] data = new byte[fs.Length];
//循环读取文件
while ((len = fs.Read(buffer, 0, buffer.Length)) != 0)
{
for (int j = 0; j < len; j )
{
data[i ] = buffer[j];
}
}
//将读取到的字节转换为string
Console.WriteLine(Encoding.UTF8.GetChars(data));
//数据写入
FileStream write = new FileStream("./demo_copy.txt", FileMode.Create, FileAccess.Write);
//重置指针
fs.Seek(0, SeekOrigin.Begin);
while ((len = fs.Read(buffer, 0, buffer.Length)) != 0)
{
write.Write(buffer, 0, len);
}
fs.Dispose();
write.Dispose();
第23行用到了一个方法Seek(),这个是用来设置当前文件指针的位置的,一般情况下,文件读到哪指针就指到哪,而通过这个方法,可以重新设置指针的位置,它的第一个参数是偏移量,为正数则向后移动,为负数则向前移动,第二个参数是SeekOrigin枚举,它有三个成员,Begin,End,Current,分别指示文件的开始,结束和当前位置,偏移量根据这个枚举值进行移动。
另外,操作结束后要及时释放资源,或者一开始使用using引用要释放的对象。
本节到此结束...