- 介绍
- 具体案例
- 创建Zip压缩文件
- 使用GZipStream类压缩文件
- 实现本地进程之间的通信
- 单向管道通信
- 总结
随着.net core
越来越流行,对.net core
基础知识的了解,实际应用等相关的知识也应该有所了解。所以就有了这篇文章,案例都是来自阅读的书籍,或者实际工作中感觉比较有用的应用。分享亦总结。
本文主要介绍 .net core
相关的文件与I/O案例。
【导语】
ZipArchive
类支持对 zip
压缩文档的基本管理,压缩文件中的每个文件(实体)由 ZipArchiveEntry
类进行维护。调用 ZipArchiveEntry
实例的 Delete
方法可以将文件从 zip
文档中删除;调用 Open
方法将得到一个流实例,可以对压缩文档中的文件实体进行读写操作。
本实例将完成两项操作:首先创建一个 zip
压缩文档,并向该文档添加三个文件实体,每个实体都写入内容。然后将该压缩文档中的文件实体解压出来,分别存储到三个文件中。
【操作流程】
步骤1:新建控制台应用程序项目。
步骤2:声明一个 string
类型的变量,存放文件名称。
string zipFile = "demo.zip";
步骤3:创建 zip
压缩文档,并放入三个实体。
using (FileStream outfs = File.Create(zipFile))
{
using (ZipArchive zip = new ZipArchive(outfs, ZipArchiveMode.Create))
{
// 第一个文件
ZipArchiveEntry et1 = zip.CreateEntry("docs/doc1.txt");
using (Stream stream = et1.Open())
{
using (StreamWriter writer = new StreamWriter(stream))
{
writer.Write("示例文档 A");
}
}
// 第二个文件
ZipArchiveEntry et2 = zip.CreateEntry("docs/doc2.txt");
using (Stream stream = et2.Open())
{
using (StreamWriter writer = new StreamWriter(stream))
{
writer.Write("示例文档 B");
}
}
// 第三个文件
ZipArchiveEntry et3 = zip.CreateEntry("docs/doc3.txt");
using (Stream stream = et3.Open())
{
using (StreamWriter writer = new StreamWriter(stream))
{
writer.Write("示例文档 C");
}
}
}
}
若要创建新的压缩文档,在调用 ZipArchive
类的构造函数时,不仅要提供基础文件的流,还要将 mode
参数指定为 ZipArchiveMode.Create
,否则会发生异常。调用 CreateEntry
方法时值当的实体名称,允许使用相对路径。
步骤4:将已经创建的 zip
压缩文档中的三个实体解压出来,并存放到本文文件夹中。
using(FileStream instream = File.OpenRead(zipFile))
{
using(ZipArchive zip = new ZipArchive(instream))
{
foreach(ZipArchiveEntry et in zip.Entries)
{
using(Stream stream = et.Open())
{
using(FileStream fsout = File.Create(et.Name))
{
stream.CopyTo(fsout);
}
}
}
}
}
步骤5:运行应用程序项目。自行查看被解压的三个文件。
使用GZipStream类压缩文件【导语】
GZIP
(全称 GNUzip
)最终由 Jean-loup Gailly
和 Mark Adler
开发,用于 Unix
系统的文件压缩,通常文件扩展名为 .gz
,是非常普遍的一种数据压缩格式,或者说是一种文件格式。框架以 GZipStream
类来封装 GZip
算法相关功能,使用方法与 DeflateStream
相同。
本实例将提示用户输入待压缩文件的路径,确认后使用过 GZip
算法压缩文件,并在应用所在目录下输出名为 demo.gz
的文件。
【操作流程】
步骤1:新建控制台应用程序项目。
步骤2:获取用户输入的待压缩文件路径。
Console.WriteLine("请输入待压缩文件的路径:");
string inFilePath = Console.ReadLine();
步骤3:声明一个 string
类型的变量,表示输入的压缩文件名。
string outFileName = "demo.gz";
步骤4:对输入文件进行压缩处理。
using (FileStream fsIn = File.OpenRead(inFilePath))
using (FileStream fsOut = File.Create(outFileName))
{
using (GZipStream gz = new GZipStream(fsOut, CompressionMode.Compress))
{
fsIn.CopyTo(gz);
}
}
步骤5:分别输出压缩前后的文件大小,以供对比。
FileInfo info1 = new FileInfo(inFilePath);
FileInfo info2 = new FileInfo(outFileName);
Console.WriteLine($"压缩前,文件大小:{info1.Length}");
Console.WriteLine($"压缩后,文件大小:{info2.Length}");
步骤6:运行应用程序项目,结果如下。
【导语】
命名管道是一种比较简单易用的通信方式,它支持同一台计算机上进程之间,或者不同计算机上进程与进程之间的数据传输。要使用命名管道进行进程间的通信,需要用到 System.IO.Pipes
命名空间中的以下两个类。
(1)NamedPipeServerStream
类:通信中的服务器,实例化该类型之后,需要调用 WaitForConnection
方法或者 WaitForConnectionAsync
方法列来侦听客户端连接。
(2)NamedPipeClientStream
类:通信中的客户端,实例化该类型后,调用 Connect
方法可以向服务器发起连接请求。
NamedPipeServerStream
类和 NamedPipeClientStream
类都是 Stream
的派生类,因此它们都可以以流的当视发送或接收数据。
本实例的解决方案中包含两个应用程序项目,分别表示通信中的两个进程。当两个应用程序启动后,用户可以在客户端通过键盘输入消息后发送,服务器会显示接收到的消息。
【操作流程】
步骤1:新建两个控制台应用程序项目。
首先实现服务器应用程序。
步骤2:引入命名空间。
using System;
using System.IO;
using System.IO.Pipes;
步骤3:在 using
语句块中实例化 NamedPipeServerStream
类。
using(NamedPipeServerStream server = new NamedPipeServerStream("demo"))
{
...
Console.WriteLine("按任意键退出。");
Console.Read();
}
调用 NamedPipeServerStream
构造函数时,传递一个自定义名称,此名称可以唯一确定该服务器管道。
步骤4:等待客户端连接。
server.WaitForConnection();
步骤5:使用 StreamReader
类来读取从可达发送来的消息。
try
{
using(StreamReader reader = new StreamReader(server))
{
string msg = null;
while((msg = reader.ReadLine()) != null)
{
Console.WriteLine($"客户端:{msg}");
}
}
}
catch
{
Console.WriteLine("发生了错误。");
}
接下来是客户端应用程序。
步骤6:引入命名空间。
using System;
using System.IO;
using System.IO.Pipes;
步骤7:实例化 NamedPipeClientStream
类。在调用构造函数是,传递给 pipeName
参数的管道名称必须与服务器管道的名称匹配,否则无法进行连接。
using(NamedPipeClientStream client = new NamedPipeClientStream("demo"))
{
...
}
步骤8:向服务器发出连接请求。
client.Connect();
步骤9:使用 StreamWriter
类来写入要发送的消息。
using(StreamWriter writer = new StreamWriter(client))
{
writer.AutoFlush = true;
while(true)
{
Console.WriteLine("请输入要发送的内容:");
string msg = Console.ReadLine();
if (!string.IsNullOrWhiteSpace(msg))
{
writer.WriteLine(msg);
}
}
}
将 AutoFlush
属性设置为 true
,可以使 StreamWriter
实例每次写入数据后自动将数据提交到基础的 NamedPipeClientStream
实例中,从而达到立刻发送消息的目的。
步骤10:在 Visual Studio
的“解决方案资源管理器”窗口中,右击解决方案名称,从快捷菜单中选择属性命令,打开解决方案属性窗口。
步骤11:在启动项目对话框中勾选多个启动项目,然后将服务器和客户端两个应用程序项目都设置为启动,单击确定按钮保存,这样在运行时就可以同时启动两个项目。
步骤12:按 F5
快捷间同时运行两个项目。
步骤13:在客户端输入要发送的消息,按 Enter
键确认,在服务器程序中就能看到已经接收到的消息。
【导语】
在调用 NamedPipeServerStream
类和 NamedPipeClientStream
类的构造函数时,可以传递一个 direction
参数,该参数类型是 PipeDirection
枚举,用来指定管道的通信方向,它定义了以下三个值。
(1)Out
:管道仅为输出模式,即只能写入消息。
(2)In
:管道仅为输入模式,即只读通信。
(3)InOut
:双向通信,可以写入消息,也可以读取消息。
当未指定 direction
参数的情况下,默认生成双向通信的管道(InOut
)。
本实例将实现单向通信,服务器只能用于发送消息,而客户端只能读取消息。
【操作流程】
步骤1:新建两个控制台应用程序项目。
首先实现服务器应用程序。
步骤2:引入命名空间。
using System;
using System.IO;
using System.IO.Pipes;
步骤3:实例化 NamedPipeServerStream
类。
using(NamedPipeServerStream server = new NamedPipeServerStream("test", PipeDirection.Out))
{
...
}
在调用构造函数时,明确指定 direction
参数为 Out
。
步骤4:等待客户端连接。
server.WaitForConnection();
步骤5:使用 StreamWriter
类来写入消息。
using(StreamWriter writer = new StreamWriter(server))
{
writer.AutoFlush = true;
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine("注意:可输入“end”退出。");
Console.ResetColor();
while (true)
{
Console.Write("请输入要发送的消息:");
string msg = Console.ReadLine();
if(msg.ToLower() == "end")
{
break;
}
writer.WriteLine(msg);
server.WaitForPipeDrain();
}
}
为了可以发送多条消息,发送消息的代码写在 while
循环中,当输入的内容为“end”时跳出循环。发送消息后调用一次 WaitForPipeDrain
方法,可以使服务器等待客户端收到消息后在继续发送后续消息。
以下是客户端的实现步骤。
步骤6:引入命名空间。
using System;
using System.IO;
using System.IO.Pipes;
步骤7:实例化 NamedPipeClientStream
类。
using(NamedPipeClientStream client = new NamedPipeClientStream(".", "test", PipeDirection.In))
{
...
}
该代码使用了以下重载版本的构造函数。
NamedPipeClientStream(string serverName, string pipeName, PipeDirection direction);
serverName
指定原创计算机名称,由于本例是本机进行测试,因此参数可以使用“.”或者"localhost"。direction
参数是 In
。即只读通信。
步骤8:连接服务器。
client.Connect();
步骤9:使用 StreamReader
类来读取消息。
using(StreamReader reader = new StreamReader(client))
{
string msg = null;
while((msg = reader.ReadLine()) != null)
{
Console.WriteLine($"服务器:{msg}");
}
}
步骤10:在解决方案属性中将两个应用项目都设置为启动项目。
步骤11:同时运行两个项目,在服务器上写入要发送的消息,按 Enter
键确定后,客户端会显示收到的消息。
本文到这里就结束了,下一篇将介绍序列化的知识案例。