文章的续作前文是:
C#文件操作(一)-CSDN博客https://blog.csdn.net/qq_71897293/article/details/135117922?spm=1001.2014.3001.5501
流是序列化设备的抽象表示序列化设备可以线性方式储存数据并可按照同样的方式访问一次访问一个字节此设备可以是磁盘文件网络通道内存位置或其他支持以现行方式读取的对象把设备变成抽象的就可以隐藏流的底层目标和元 (书上对于流的介绍)
FileStream类提供了很多对文件读写的方法,需要注意FileStream是对字节和字节数组操作而StreamWriter和StreamRead则是对字符数据操作,这是二者不同的地方。主要是对文件的读写操作。
举个例子:
//储存数据的字节数组
byte[] bytes = new byte[1024];
System.IO.FileStream fileStream = new System.IO.FileStream("Log.txt", System.IO.FileMode.OpenOrCreate);
//将指针移到文件的开始位置的第七个字节处
fileStream.Seek(0, System.IO.SeekOrigin.Begin);
//读取方法 Read 参数第一个:读取到的数据写入的字节数组 第二个:在字节数组中的第几个字节处放置读取的数据
//第三个:指定读取的字节数
//注意:如果要更改读取放置的位置那么字节长度也要相应减少 不然会报错
fileStream.Read(bytes,10, bytes.Length-10);
//将读取的字节数组通过 Encoding转码得到一个字符串 输出出来
System.Console.WriteLine(System.Text.Encoding.UTF8.GetString(bytes));
System.Console.ReadKey();
提示:1 FileStream有多个重载版本其中使用最多的是两个参数或三个参数的构造器。
System.IO.FileStream fileStream2= new System.IO.FileStream
("Log.txt", System.IO.FileMode.OpenOrCreate,System.IO.FileAccess.Read);
注意:
其中FileMode指定了如何打开或创建文件,FileAccess指定了流的作用 ,都是枚举类型,其中如果FileAccess 指定了流的作用是读取文件那么如果你实际是写入文件那么将会抛出异常。
举个例子:
try
{
//将要写入的信息转换为字节数组
byte[] bytes = System.Text.Encoding.UTF8.GetBytes("写入文件的信息");
//指定对文件进行OpenOrCreate 操作 流是进行写入操作
System.IO.FileStream fileStream = new System.IO.FileStream("Log.txt", System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.Write);
//将指针移动指文件结束位置 的第0个位置写入
fileStream.Seek(0, System.IO.SeekOrigin.End);
//写入
fileStream.Write(bytes, 0, bytes.Length);
}
catch (System.Exception ex)
{
System.Console.WriteLine(ex.Message);
System.Console.ReadKey();
}
注意:
文件类似的操作是很容易由各种原因引发异常,我们在对文件操作时应当使用Try语句。对异常进行处理和预防。
StreamWriter前面提到了是对字符数据进行操作。如果不需要将指针指向文件何处位置那么使用此类是很简单的。
第一种:
FileStream fileStream = new FileStream("Log.txt", FileMode.Open, FileAccess.Read);
StreamWriter writer = new StreamWriter(fileStream);
提示:可以在已经有了FileStream对象时可以这么创建
第二种:
StreamWriter writer = new StreamWriter("Log.txt",false);
示例解释:
两个参数,第二个参数是设置是否对文件进行追加,True则是在文件结束处追加在后面,False则是重头写入,或者新建一个文件写入。
举个例子:
System.IO.FileStream fileStream = new System.IO.FileStream("Log.txt", FileMode.OpenOrCreate);
System.IO.StreamWriter writer = new System.IO.StreamWriter(fileStream);
writer.WriteLine("信息1");
writer.Write("信息2");
writer.Write("信息3");
writer.Write("信息4");
writer.Write("信息5");
writer.Close();
效果:
StreamRead前面也提到了也是对字符数据进行操作。它一样有两种创建的方式和StreamWriter类似。
举个例子:
System.IO.FileStream fileStream = new System.IO.FileStream("Log.txt", System.IO.FileMode.OpenOrCreate);
System.IO.StreamReader writer = new System.IO.StreamReader(fileStream);
int charcode=default;
while (charcode!=-1)
{
Console.Write(Convert.ToChar(charcode));
charcode = writer.Read();
}
writer.Close();
//还有读取方法writer.ReadLine(); 与 writer.ReadToEnd();
Console.ReadKey();
提示:除了当前使用的方法还有ReadLine 和ReadToEnd方法。效果与直译效果一样。
当我们读取较大的文件时我们需要花费一点时间但我们不能让我们的主线程卡在读取从而无法正常与用户交互。其中我们上面使用的方法带有Async修饰的即代表异步读取,不会堵住我们的线程。
两个压缩流类举个例子:
封装的保存方法
static void SaveCompressedFile(string filename, string data)
{
FileStream fileStream =new FileStream(filename, FileMode.Create, FileAccess.Write);
GZipStream compressionStream = new GZipStream(fileStream, CompressionMode.Compress);
StreamWriter writer = new StreamWriter(compressionStream);
writer.Write(data);
writer.Close();
}
封装的读取方法
static string LoadCompressedFile(string filename)
{
FileStream fileStream =
new FileStream(filename, FileMode.Open, FileAccess.Read);
GZipStream compressionStream =
new GZipStream(fileStream, CompressionMode.Decompress);
StreamReader reader = new StreamReader(compressionStream);
string data = reader.ReadToEnd();
reader.Close();
return data;
}
使用方式:
static void Main(string[] args)
{
SaveCompressedFile("log.txt", "写入的数据");
var str = LoadCompressedFile("log.txt");
Console.WriteLine(str);
Console.ReadKey();
}
需要注意当前的保存文件是对数据进行了压缩不是改为压缩包。书上提到的压缩比例是80:1。我们只需要了解如何使用就可以了
FileSystemWatcher类有一个公共无参的构造函数创建该对象实例后可以通过属性 EnableRaisingEvents为true的时候则代表开始监控 Path属性代表监控文件的路径 Filter代表监控哪种文件格式 *.*代表所有文件。NotifyFilter属性代表要监控的类型 我们可以使用二元OR运算符 来合并这些枚举值。
举个例子:
watcher.NotifyFilter = NotifyFilters.LastWrite |
NotifyFilters.FileName | NotifyFilters.Size;
注意: watcher 是FileSystemWatcher的实例
可以给当前类型创建多个处理事件。
watcher.Deleted += (s, e) => { };
watcher.Renamed += (s, e) =>{ };
watcher.Changed += (s, e) => { };
watcher.Created += (s, e) => { };
示例解释:分别创建了删除触发的世界更改触发的事件新建触发的事件重命名触发的事件
本章学习完结