.net core精彩实例分享 -- 文件与I/O

介绍

随着.net core越来越流行,对.net core 基础知识的了解,实际应用等相关的知识也应该有所了解。所以就有了这篇文章,案例都是来自阅读的书籍,或者实际工作中感觉比较有用的应用。分享亦总结。

本文主要介绍 .net core 相关的文件与I/O案例。

具体案例

创建Zip压缩文件

【导语】

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 GaillyMark 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 键确定后,客户端会显示收到的消息。

在这里插入图片描述

总结

本文到这里就结束了,下一篇将介绍序列化的知识案例。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值