当前位置:网站首页 / .NET CORE / 正文

ay的C#8.0和net5高级编程笔记9-处理文件、流和序列化

时间:2021年04月25日 | 作者 : aaronyang | 分类 : .NET CORE | 浏览: 236次 | 评论 0

此节开始,使用vs2019

控制台讲解 处理文件、流、序列化

image.pngimage.pngimage.png

路径在 不同操作系统路径不同的

using System;
using static System.Console;
using static System.IO.Directory;
using static System.IO.Path;
using static System.Environment;

namespace WorkingWithFileSystems
{
    class Program
    {
        static void Main(string[] args)
        {
            WriteLine("{0,-33}{1}","Path.PathSeparator",PathSeparator);
            WriteLine("{0,-33}{1}", "Path.DirectorySeparatorChar", DirectorySeparatorChar);
            WriteLine("{0,-33}{1}", "Directory.GetCurrentDirectory()", GetCurrentDirectory());
            WriteLine("{0,-33}{1}", "Environment.CurrentDirectory", CurrentDirectory);
            WriteLine("{0,-33}{1}", "Environment.SystemDirectory", SystemDirectory);
            WriteLine("{0,-33}{1}", "Path.GetTempPath()", GetTempPath());
            WriteLine("特殊目录");

            WriteLine("{0,-33}{1}", ".System", GetFolderPath(SpecialFolder.System));
            WriteLine("{0,-33}{1}", ".ApplicationData", GetFolderPath(SpecialFolder.ApplicationData));
            WriteLine("{0,-33}{1}", ".MyDocuments", GetFolderPath(SpecialFolder.MyDocuments));
            WriteLine("{0,-33}{1}", ".Personal", GetFolderPath(SpecialFolder.Personal));

            Console.ReadLine();
        }
    }
}

image.png

Environment成员很多


Windows使用反斜杠作为目录分隔符,macOS和Linux使用正斜杠



驱动器

        WriteLine("{0,-30} | {1,-10} | {2,-7} | {3,18} | {4,18}","名称","类型","Format","大小","可用大小");
            foreach (DriveInfo item in DriveInfo.GetDrives())
            {
                if (item.IsReady)
                {
                    WriteLine("{0,-30} | {1,-10} | {2,-7} | {3,18} | {4,18}", item.Name, item.DriveType,item.DriveFormat, item.TotalSize, item.AvailableFreeSpace);
                }
                else
                {
                    WriteLine("{0,-30} | {1,-10} ", item.Name, item.DriveType);
                }
            }

image.png



管理目录

    using System;
    using static System.Console;
    using static System.IO.Directory;
    using static System.IO.Path;
    using static System.Environment;
    using System.IO;

    namespace WorkingWithFileSystems
    {
        class Program
        {
            static void Main(string[] args)
            {
                var newfolderRoot = Combine(GetFolderPath(SpecialFolder.Personal), "CoreCode");
                var newfolder = Combine(newfolderRoot, "Chapter09","NewFolder");
                if (!Directory.Exists(newfolder))
                {
                    CreateDirectory(newfolder);
                }
                Delete(newfolderRoot, recursive: true);
           
            

                Console.ReadLine();
            }
        }
    }

image.png



管理文件

  var dir = Combine(GetFolderPath(SpecialFolder.Personal), "Code/Chapter09/OutputFiles");
            CreateDirectory(dir);
            var textfile = Combine(dir, "Dummy.txt");
            var backupfile = Combine(dir, "Dummy.bak");
            WriteLine($"写{textfile}");
            if (File.Exists(textfile))
            {
                File.Delete(textfile);
            }
            using (StreamWriter tw=File.CreateText(textfile))
            {
                tw.WriteLine("Hello Ay");
            }
            //备份
            File.Copy(textfile, backupfile, true);
            WriteLine($"bak文件是否存在:{File.Exists(backupfile)}");
            //删除原来的文件
            if (File.Exists(textfile))
            {
                File.Delete(textfile);
            }
            //打开备份文件
            using (StreamReader dr = File.OpenText(backupfile))
            {
                WriteLine(dr.ReadToEnd());
            }

image.png


管理路径

            Console.WriteLine($"文件夹名称:{GetDirectoryName(textfile)}");
            Console.WriteLine($"文件名称:{GetFileName(textfile)}");
            Console.WriteLine($"文件名无后缀:{GetFileNameWithoutExtension(textfile)}");
            Console.WriteLine($"文件后缀:{GetExtension(textfile)}");
            Console.WriteLine($"随机文件名:{GetRandomFileName()}");
            Console.WriteLine($"临时文件名:{GetTempFileName()}");

image.png

GetRandomFileName 方法创建零字节的文件并返回文件名

GetTempFileName 方法只返回文件名而不会创建文件


文件信息

FileInfo DirectoryInfo

  var info = new FileInfo(backupfile);
            Console.WriteLine($"{info.Length} {info.LastAccessTime} {info.IsReadOnly}");

image.png

不同操作系统中字节数可能不同


控制如何处理文件

FileOpen方法有个参数

FileMode 控制要对文件做什么,比如CreateNew,OpenOrCreate或Truncate

FileAccess 控制需要的访问级别,比如ReadWrite

FileShare 控制文件上的锁,从而允许其他进程以指定的访问级别访问,比如Read。

可以打开文件从文件中读取内容,并允许其他进程读取文件

  FileStream file = File.Open(backupfile, FileMode.Open, FileAccess.Read, FileShare.Read);
            //FileAttributes:检查FileSystemInfo派生类型Attribute属性值,例如Archive和Encrypted等,还可以检查文件或者目录的特性,如下所示:
            var bakfileInfo = new FileInfo(backupfile);
            WriteLine("文件是否压缩?{0}",bakfileInfo.Attributes.HasFlag(FileAttributes.Compressed));

image.png

====================www.ayjs.net       杨洋    wpfui.com        ayui      ay  aaronyang=======请不要转载谢谢了。=========

流读写

Stream抽象类

派生类: MemoryStream    BufferedStream    GZipStream    SslStream

所有流实现了IDisposable接口


Stream常用

CanRead    CanWrite     是否可以读写流

Length    Position    确定总字节数和流中当前的位置

Dispose()    关闭释放流

Flush()    如果流有缓冲区,就将缓冲区中的字节写入流并清除缓冲区

Read()    ReadAsync()    将指定数量的字节从流中读取到字节数组中,并向前推进位置

ReadByte()    从流中读取下一个字节,并推进位置

Seek() 将位置移动到指定的位置(前提是CanSeek为true)

Write() WriteAsync() 将字节组的内容写入流

WriteByte() 将一个字节写入流


System.IO.FileStream 字节存储在文件系统

System.IO.MemoryStream 字节存储在当前进程的内存中

System.Net.Sockets.NetworkStream 将字节存储在网络位置


System.Security.Cryptography.CryptoStream  对流进行加密和解密

System.IO.Compression.GzipStream    DeflateStream 压缩和解压流

System.Net.Security.AuthenticatedStream 跨流发送凭据


常用辅助类

System.IO    StreamReader 从底层流读取文本

System.IO    StreamWriter 以文本的形式写入底层流

System.IO    BinaryReader    从流中读取.NET类型,例如ReadDecimal 从底层流读取后面的16字节,ReadInt32 读取后面4字节

System.IO    BinaryWriter    作为.NET类型写入流,带有decimal参数的write方法向底层流写入16字节, 带有int的写入4字节

System.Xml    XmlReader    以XML的形式从底层流读取数据

System.Xml    XmlWriter    以XML的形式写入底层流



写入文件流

    string textFile = Combine(CurrentDirectory, "stream.txt");

            using (StreamWriter text = File.CreateText(textFile))
            {
                text.WriteLine("AY");
                text.WriteLine("2021");
                text.WriteLine("合肥");
            }
            Console.WriteLine(File.ReadAllText(textFile));

image.png

写入Xml流

    string xmlFile = Combine(CurrentDirectory, "stream.xml");

            using (FileStream xmlFileStream = File.Create(xmlFile))
            {
                using (XmlWriter xml=XmlWriter.Create(xmlFileStream,new XmlWriterSettings { Indent = true }))
                {
                    xml.WriteStartDocument();
                    xml.WriteStartElement("infos");
                    xml.WriteElementString("info", "AY");
                    xml.WriteElementString("info", "2021");
                    xml.WriteElementString("info", "合肥");
                    xml.WriteEndDocument();
                }
            }

            Console.WriteLine(File.ReadAllText(xmlFile));

image.png


当打开文件进行读写,使用.NET之外的资源,这些资源又称为非托管资源,必须在处理完之后释放。可以在finally块中调用Dispose方法。

       string xmlFile = Combine(CurrentDirectory, "stream.xml");
            FileStream xmlFileStream = null;
            XmlWriter xml = null;
            try
            {
                using (xmlFileStream = File.Create(xmlFile))
                {
                    using (xml = XmlWriter.Create(xmlFileStream, new XmlWriterSettings { Indent = true }))
                    {
                        xml.WriteStartDocument();
                        xml.WriteStartElement("infos");
                        xml.WriteElementString("info", "AY");
                        xml.WriteElementString("info", "2021");
                        xml.WriteElementString("info", "合肥");
                        xml.WriteEndDocument();
                    }
                }

                Console.WriteLine(File.ReadAllText(xmlFile));
            }
            catch (Exception ex)
            {
                Console.WriteLine($"{ex.GetType()} {ex.Message}");
            }
            finally
            {
                xmlFileStream?.Dispose();
                xml?.Dispose();
            }

效果同上


压缩流,解压流 GZIP

xml占用空间,可以使用一种名为GZIP的常见压缩算法压缩XML

using System.IO.Compression;

 string gzipFile = Combine(CurrentDirectory, "streams.gzip");
            FileStream fs = File.Create(gzipFile);
            using (GZipStream compressor = new GZipStream(fs, CompressionMode.Compress))
            {
                using (XmlWriter xml = XmlWriter.Create(compressor))
                {
                    xml.WriteStartDocument();
                    xml.WriteStartElement("infos");
                    xml.WriteElementString("info", "AY");
                    xml.WriteElementString("info", "2021");
                    xml.WriteElementString("info", "合肥");
                    xml.WriteEndDocument();
                }
            }
            //输出压缩的文件
            WriteLine("{0} 包含 {1:N0} 字节",gzipFile,new FileInfo(gzipFile).Len    gth);

            WriteLine("压缩的内容");
            WriteLine(File.ReadAllText(gzipFile));

            WriteLine("读取压缩的内容");

            fs = File.Open(gzipFile,FileMode.Open);
            using (GZipStream decom=new GZipStream(fs,CompressionMode.Decompress))
            {
                using (XmlReader xr=XmlReader.Create(decom))
                {
                    while (xr.Read())
                    {
                        if((xr.NodeType==XmlNodeType.Element) && xr.Name == "info")
                        {
                            xr.Read();
                            WriteLine(xr.Value);
                        }
                    }
                }
            }

102个字节

image.png



使用Brotli算法压缩

NC2.1引入了Brotli算法,类似于Deflate和GZIP,但是输出密度大20%左右


Brotli最初发布于2015年,用于网络字体的离线压缩。Google软件工程师在2015年9月发布了包含通用无损数据压缩的Brotli增强版本,特别侧重于HTTP压缩。其中的编码器被部分改写以提高压缩比,编码器和解码器都提高了速度,流式API已被改进,增加更多压缩质量级别。新版本还展现了跨平台的性能改进,以及减少解码所需的内存。

与常见的通用压缩算法不同,Brotli使用一个预定义的120千字节字典。该字典包含超过13000个常用单词、短语和其他子字符串,这些来自一个文本和HTML文档的大型语料库。预定义的算法可以提升较小文件的压缩密度。

使用brotli取代deflate来对文本文件压缩通常可以增加20%的压缩密度,而压缩与解压缩速度则大致不变。


支持Brotli压缩算法的浏览器使用的内容编码类型为br,例如以下是Chrome浏览器请求头里Accept-Encoding的值:Accept-Encoding: gzip, deflate, sdch, br



82个字节,文件变的更小了

  string filePath = Combine(CurrentDirectory, "streams.brotli");
            FileStream fs = File.Create(filePath);

            using (Stream compressor = new BrotliStream(fs, CompressionMode.Compress))
            {
                using (XmlWriter xml = XmlWriter.Create(compressor))
                {
                    xml.WriteStartDocument();
                    xml.WriteStartElement("infos");
                    xml.WriteElementString("info", "AY");
                    xml.WriteElementString("info", "2021");
                    xml.WriteElementString("info", "合肥");
                    xml.WriteEndDocument();
                }
            }
            //输出压缩的文件
            WriteLine("{0} 包含 {1:N0} 字节", filePath, new FileInfo(filePath).Length);

            WriteLine("压缩的内容");
            WriteLine(File.ReadAllText(filePath));

            WriteLine("读取压缩的内容");

            fs = File.Open(filePath, FileMode.Open);
            using (Stream decom = new BrotliStream(fs, CompressionMode.Decompress))
            {
                using (XmlReader xr = XmlReader.Create(decom))
                {
                    while (xr.Read())
                    {
                        if ((xr.NodeType == XmlNodeType.Element) && xr.Name == "info")
                        {
                            xr.Read();
                            WriteLine(xr.Value);
                        }
                    }
                }
            }

image.png



使用管道的高性能流

NC2.1 引入管道 ,感兴趣看这篇:查看

image.png



 异步流

C#8.0 和 NC3.0 引入了流的异步处理,后面第13篇博客会讲

https://docs.microsoft.com/zh-cn/dotnet/csharp/whats-new/tutorials/generate-consume-asynchronous-stream

image.png

编码

ASCII

UTF-8

UTF-7

UTF-16

UTF-32

ANSI/ISO编码

string msg = "Hello AY";
            byte[] en1=System.Text.Encoding.UTF8.GetBytes(msg);
            Console.WriteLine("HelloAY的编码后的长度,"+en1.Length);
            Console.WriteLine("Byte HEX CHAR");
            foreach (var en in en1)
            {
                Console.WriteLine($"{en,4} {en.ToString("X"),4} {(char)en,5}");
            }
            string decodeEn1 = System.Text.Encoding.UTF8.GetString(en1);
            Console.WriteLine(decodeEn1);

image.png

不同的编码,占用的字节数不一样


对文件中的文本进行编码和解码

            var reader = new StreamReader(stream, System.Text.Encoding.UTF8);

            var writer = new StreamWriter(stream, System.Text.Encoding.UTF8);



序列化对象

常见的有两种,XML和JS对象的Json

NC有多个类,可以序列化为XML和JSON,也可以反序列化。


XMl的 XmlSerializer

using System;
using static System.IO.Path;
using static System.Environment;
using System.IO;
using System.Collections.Generic;
using System.Xml.Serialization;
   var p = new List<Person>();
            p.Add(new Person { Name = "杨洋1", Born = new DateTime(1991, 4, 4), Salary = 1000 });
            p.Add(new Person { Name = "杨洋2", Born = new DateTime(1992, 5, 21), Salary = 2000 });
            p.Add(new Person
            {
                Name = "杨洋3",
                Born = new DateTime(1991, 3, 23),
                Salary = 6000m,
                Children = new HashSet<Person>
                {
                    new Person { Name = "ay1", Born = new DateTime(1992, 1, 4), Salary = 11000 },
                    new Person { Name = "ay1", Born = new DateTime(1999, 5, 6), Salary = 500M }
                }
            });
            var xs = new XmlSerializer(typeof(List<Person>));
            string path = Combine(CurrentDirectory, "people.xml");
            using (FileStream stream = File.Create(path))
            {
                xs.Serialize(stream, p);
            }
            //反序列化
            using (FileStream xmlLoad=File.Open(path,FileMode.Open))
            {
               var _1=(List<Person>) xs.Deserialize(xmlLoad);
                foreach (var item in _1)
                {
                    Console.WriteLine($"{item.Name} {item.Born} {item.Salary}");
                    if (item.Children.Count > 0)
                    {
                        foreach (var subitem in item.Children)
                        {
                            Console.WriteLine($"\t\t{subitem.Name} {subitem.Born} {subitem.Salary}");
                        }
                    }
                }
            }

image.png

可以使用xml的一些特性,使XML更紧凑

修改对象

public class Person
    {
        [XmlAttribute("sa")]
        public decimal Salary { get; set; }
        [XmlAttribute("na")]
        public string Name { get; set; }
        public HashSet<Person> Children { get; set; }
        [XmlAttribute("bo")]
        public DateTime Born { get; set; }
    }

image.png

这样名字更短了,文件更短


Json的JsonSerializer

双击程序集名字

image.png

可以编辑csproj,在vs2019中 提示都有了

image.png

在vs2019中,也可以nuget方式

image.png

搜索newtonsoft.json,然后 你安装就行了

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net5.0</TargetFramework>
  </PropertyGroup>
	<ItemGroup>
		<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
	</ItemGroup>
</Project>
            var p = new List<Person>();
            p.Add(new Person { Name = "杨洋1", Born = new DateTime(1991, 4, 4), Salary = 1000 });
            p.Add(new Person { Name = "杨洋2", Born = new DateTime(1992, 5, 21), Salary = 2000 });
            p.Add(new Person
            {
                Name = "杨洋3",
                Born = new DateTime(1991, 3, 23),
                Salary = 6000m,
                Children = new HashSet<Person>
                {
                    new Person { Name = "ay1", Born = new DateTime(1992, 1, 4), Salary = 11000 },
                    new Person { Name = "ay1", Born = new DateTime(1999, 5, 6), Salary = 500M }
                }
            });
            string jsonPath = Combine(CurrentDirectory, "person.json");
            using (StreamWriter sw=File.CreateText(jsonPath))
            {
                var jss = new Newtonsoft.Json.JsonSerializer();
                jss.Serialize(sw,p);
            }
            Console.WriteLine(File.ReadAllText(jsonPath));

image.png



高性能JSON处理

NC3.0引入 SYstem.Text.Json类,优化性能。

Json.NET是通过读取UTF-16来实现的。使用UTF-8读取JSON文档能带来更好的性能。

因为包括Http在内的大多数网络协议都使用UTF-8,而且可以避免在UTF-8与Json.NET的Unicode字符串值之间来回转换。

https://devblogs.microsoft.com/dotnet/try-the-new-system-text-json-apis/

引入

using System.Threading.Tasks;

using NuJson = System.Text.Json.JsonSerializer;


顶部

 static void Main(string[] args)

修改为

 static async Task Main(string[] args)


现在解析

          var p = new List<Person>();
            p.Add(new Person { Name = "杨洋1", Born = new DateTime(1991, 4, 4), Salary = 1000 });
            p.Add(new Person { Name = "杨洋2", Born = new DateTime(1992, 5, 21), Salary = 2000 });
            p.Add(new Person
            {
                Name = "杨洋3",
                Born = new DateTime(1991, 3, 23),
                Salary = 6000m,
                Children = new HashSet<Person>
                {
                    new Person { Name = "ay1", Born = new DateTime(1992, 1, 4), Salary = 11000 },
                    new Person { Name = "ay1", Born = new DateTime(1999, 5, 6), Salary = 500M }
                }
            });
            string jsonPath = Combine(CurrentDirectory, "person.json");
            using (StreamWriter sw = File.CreateText(jsonPath))
            {
                var jss = new Newtonsoft.Json.JsonSerializer();
                jss.Serialize(sw, p);
            }
            var _text = File.ReadAllText(jsonPath);
            Console.WriteLine(_text);

            Console.WriteLine();
            Console.WriteLine("开始解析");
            using (FileStream jsonLoad=File.Open(jsonPath,FileMode.Open))
            {
                var loadPeople = (List<Person>)await NuJson.DeserializeAsync(jsonLoad, typeof(List<Person>));
                foreach (var item in loadPeople)
                {
                    Console.WriteLine($"{item.Name} {item.Born} {item.Salary}");
                    if (item.Children!=null && item.Children.Count > 0)
                    {
                        foreach (var subitem in item.Children)
                        {
                            Console.WriteLine($"\t\t{subitem.Name} {subitem.Born} {subitem.Salary}");
                        }
                    }
                }
            }

image.png



www.ayjs.net

推荐您阅读更多有关于“C#8.0core3,”的文章

猜你喜欢

额 本文暂时没人评论 来添加一个吧

发表评论

必填

选填

选填

必填

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

  查看权限

合肥科大智能常年招聘C# .NET CORE,vue前端,JAVA开发,有想换工作的私聊我AY唯一QQ:875556003和AY交流

抖音号:wpfui 工作是wpf,不接活,目前主要折腾maui

AYUI8社区版Github地址:前往获取

杨洋(AaronYang简称AY,安徽六安人)目前是个人,还没公司AY唯一QQ:875556003和AY交流

高中学历,2010年开始web开发,2015年1月17日开始,兴趣学习研究WPF

声明:AYUI7个人与商用免费,源码可购买。部分DEMO不免费.AY主要靠卖技术服务挣钱

不是从我处购买的ayui7源码,我不提供任何技术服务,如果你举报从哪里买的,我可以帮你转正为我的客户,并送demo

查看捐赠

AYUI7.X MVC教程 更新如下:

第一课 第二课 程序加密教程

vs2015 企业版密钥HM6NR-QXX7C-DFW2Y-8B82K-WTYJV

vs2017 企业版密钥NJVYC-BMHX2-G77MM-4XJMR-6Q8QF

标签列表