c#打包文件解压缩 C#中使用委托、接口、匿名方法、泛型委托实现加减乘除算法 一个简单例子理解C#的协变和逆变 对于过长字符串的大小比对...

首先要引用一下类库:using Ionic.Zip;这个类库可以到网上下载。

  下面对类库使用的封装方法:

得到指定的输入流的ZIP压缩流对象

复制代码
        /// 
            /// 得到指定的输入流的ZIP压缩流对象【原有流对象不会改变】
            /// 
            /// 
            /// 
            public static Stream ZipCompress(Stream sourceStream, string entryName = "zip")
            {
                MemoryStream compressedStream = new MemoryStream();
                if (sourceStream != null)
                {
                    long sourceOldPosition = 0;
                    try
                    {
                        sourceOldPosition = sourceStream.Position;
                        sourceStream.Position = 0;
                        using (ZipFile zip = new ZipFile())
                        {
                            zip.AddEntry(entryName, sourceStream);
                            zip.Save(compressedStream);
                            compressedStream.Position = 0;
                        }
                    }
                    catch
                    {
                    }
                    finally
                    {
                        try
                        {
                            sourceStream.Position = sourceOldPosition;
                        }
                        catch
                        {
                        }
                    }
                }
                return compressedStream;
            }
复制代码

得到指定的字节数组的ZIP解压流对象

 

复制代码
/// 
            /// 得到指定的字节数组的ZIP解压流对象
            /// 当前方法仅适用于只有一个压缩文件的压缩包,即方法内只取压缩包中的第一个压缩文件
            /// 
            /// 
            /// 
            public static Stream ZipDecompress(byte[] data)
            {
                Stream decompressedStream = new MemoryStream();
                if (data != null)
                {
                    try
                    {
                        MemoryStream dataStream = new MemoryStream(data);
                        using (ZipFile zip = ZipFile.Read(dataStream))
                        {
                            if (zip.Entries.Count > 0)
                            {
                                zip.Entries.First().Extract(decompressedStream);
                                // Extract方法中会操作ms,后续使用时必须先将Stream位置归零,否则会导致后续读取不到任何数据
                                // 返回该Stream对象之前进行一次位置归零动作
                                decompressedStream.Position = 0;
                            }
                        }
                    }
                    catch
                    {
                    }
                }
                return decompressedStream;
            }
复制代码

 

压缩ZIP文件

 

复制代码
  /// 
            /// 压缩ZIP文件
            /// 支持多文件和多目录,或是多文件和多目录一起压缩
            /// 
            /// 待压缩的文件或目录集合
            /// 压缩后的文件名
            /// 是否按目录结构压缩
            /// 成功:true/失败:false
            public static bool CompressMulti(List list, string strZipName, bool IsDirStruct)
            {
                try
                {
                    using (ZipFile zip = new ZipFile(Encoding.Default))//设置编码,解决压缩文件时中文乱码
                    {
                        foreach (string path in list)
                        {
                            string fileName = Path.GetFileName(path);//取目录名称
                            //如果是目录
                            if (Directory.Exists(path))
                            {
                                if (IsDirStruct)//按目录结构压缩
                                {
                                    zip.AddDirectory(path, fileName);
                                }
                                else//目录下的文件都压缩到Zip的根目录
                                {
                                    zip.AddDirectory(path);
                                }
                            }
                            if (File.Exists(path))//如果是文件
                            {
                                zip.AddFile(path,"imges");
                            }
                        }
                        zip.Save(strZipName);//压缩
                        return true;
                    }
                }
                catch (Exception)
                {
                    return false;
                }
            }
复制代码

 

解压ZIP文件

 

复制代码
/// 
            /// 解压ZIP文件
            /// 
            /// 待解压的ZIP文件
            /// 解压的目录
            /// 是否覆盖
            /// 成功:true/失败:false
            public static bool Decompression(string strZipPath, string strUnZipPath, bool overWrite)
            {
                try
                {
                    ReadOptions options = new ReadOptions();
                    options.Encoding = Encoding.Default;//设置编码,解决解压文件时中文乱码
                    using (ZipFile zip = ZipFile.Read(strZipPath, options))
                    {
                        foreach (ZipEntry entry in zip)
                        {
                            if (string.IsNullOrEmpty(strUnZipPath))
                            {
                                strUnZipPath = strZipPath.Split('.').First();
                            }
                            if (overWrite)
                            {
                                entry.Extract(strUnZipPath, ExtractExistingFileAction.OverwriteSilently);//解压文件,如果已存在就覆盖
                            }
                            else
                            {
                                entry.Extract(strUnZipPath, ExtractExistingFileAction.DoNotOverwrite);//解压文件,如果已存在不覆盖
                            }
                        }
                        return true;
                    }
                }
                catch (Exception)
                {
                    return false;
                }
            }
复制代码

 

 

 

使用C#实现加减乘除算法经常被用作新手练习。本篇来分别体验通过委托、接口、匿名方法、泛型委托来实现。

使用委托实现

加减乘除拥有相同的参数个数、类型和返回类型,首先想到了使用委托实现。

复制代码
//创建一个委托
public delegate decimal MathOperation(decimal left, decimal right);

//创建方法参数和返回结果符合委托的定义
public static decimal Add(decimal left, decimal right)
{
    return left + right;
}

public static decimal Subtract(decimal left, decimal right)
{
    return left - right;
}

public static decimal Multiply(decimal left, decimal right)
{
    return left * right;
}

public static decimal Divide(decimal left, decimal right)
{
    return left / right;
}

//返回委托类型
private static MathOperation GetOperation(char oper)
{
    switch(oper)
    {
        case '+': return Add;
        case '-': return Subtract;
        case '*': return Multiply;
        case '/': return Divide;
    }
    
    throw new NotSupportedException("");
}

//封装一个方法用来把操作数和符号考虑进来,返回委托类型
private static decimal Eval(string expr)
{
    var elements = expr.Split(new []{' '}, 3);
    var left = Decimal.Parse(elements[0]);
    var right = Decimal.Parse(elements[1]);
    var ope = elements[2][0];
    
    return GetOperation(op)(left, right);
}

void Main()
{
    Console.WriteLine(Eval("1 3 +"));
}
复制代码

使用接口实现


以上,委托用在了方法层面。如果在类层面,也可用接口封装加减乘除的共性。

复制代码
public interface IMathOperation
{
    decimal Compute(decimal left, decimal right);
}

public class AddOperation : IMathOperation
{
    decimal Compute(decimal left, decimal right)
    {
        return left + right;
    }
}

public class SubtractOperation : IMathOperation
{
    decimal Compute(decimal left,, decimal right)
    {
        return left - right;
    }
}

public class MultiplyOperation : IMathOperation
{
    decimal Compute(decimal left, decimal right)
    {
        return left * right;
    }
}

public class DivideOperation : IMathOperation
{
    decimal Compute(decimal left, decimal right)
    {
        return left/right;
    }
}

//获取接口类型
private static IMathOperation GetOperation(char oper)
{
    switch(oper)
    {
        case '+': return new AddOperation();
        case '-': return new SubtractOperation();
        case '*': return new MultiplyOperation();
        case '/': return new DivideOperation();
    }
    
    throw new NotSupportedException("");
}

...
复制代码

使用匿名方法


委托还可以结合匿名方法一起使用。

复制代码
public delegate decimal MathOperation(decimal left, decimal right);

private static MathOperation GetOperation(char oper)
{
    switch(oper)
    {
        case '+': return delgate(decimal left, decimal right) {return left + right;};
        case '-': return delgate(decimal left, decimal right) {return left - right;};
        case '*': return delgate(decimal left, decimal right) {return left * right;};
        case '/': return delgate(decimal left, decimal right) {return left / right;};
    }
    
    throw new NotSupportedException("");
}
复制代码

泛型委托


而用泛型委托实现更简洁。

 

复制代码
private static Func GetOperation(char oper)
{
    switch(oper)
    {
        case '+': return (left, right) => left + right;
        case '-': return (left, right) => left - right;
        case '*': return (left, right) => left * right;
        case '/': return (left, right) => left / right;
    }
    
    throw new NotSupportedExcepton("");
}
复制代码
 
 
 
 
 
 

关于协变逆变,SolidMango的解释是比较可取的。有了协变,比如,在需要返回IEnumerable类型的时候,可以使用IEnmerable来替代;有了逆变,比如,在需要接收IComparable类型形参方法中,可以使用IComparable类型实参来替代。

协变

先来体会协变。有2个具有继承关系的父类和子类。

复制代码
    public class Animal

    {
        public string Name { get; set; }
    }

    public class Dog : Animal
    {
        public Dog(string dogName)
        {
            Name = dogName;
        }
    }
复制代码

现在有一个帮助类的方法的形参类型是父类集合IEnumerable

复制代码
    public class MyHelper

    {
        public void PrintAnimalNames(IEnumerable animals)
        {
            foreach (var animal in animals)
            {
                Console.WriteLine(animal.Name);
            }
        }
    }
复制代码

有了协变,可以在PrintAnimalNames方法中传入IEnumerable类型的实参替代IEnumerable类型。

复制代码
        static void Main(string[] args)

        {

            List dogs = new List()

            {

                new Dog("小狗petty"),

                new Dog("小狗lily")

            };

            //协变

            IEnumerable animals = dogs;

            MyHelper myHelper = new MyHelper();

            myHelper.PrintAnimalNames(animals);

            Console.ReadKey();

        }
复制代码

可见,在方法中基于基类接口类型的形参,调用该方法的时候可以传入派生类接口类型的实参。      

 

逆变

再来体会逆变。依然是2个具有继承关系的父类和子类。

复制代码
    public class Animal 
    {
        public string Name { get; set; }

        public int Age { get; set; }
    }
    public class Cat : Animal
    {
        public Cat(string catName, int catAge)

        {
            Name = catName;

            Age = catAge;
        }
    }
复制代码

现在,我们想比较基类Animal的两个实例,为此,有必要专门写一个类让他实现IComparer接口。

复制代码
    public class AnimalSizeComparator : IComparer
    {
        public int Compare(Animal x, Animal y)
        {
            if (x != null && y != null)
            {
                if (x.Age > y.Age)
                {
                    return 1;
                }
                else if (x.Age == y.Age)
                {
                    return 0;
                }
                else
                {
                    return -1;
                }
            }
            else
            {
                return -1;
            }
        }
    }
复制代码

在帮助类中的方法中,针对Cat进行比较,方法接收IComparer类型的形参。

复制代码
    public class MyHelper

    {

        public void CompareCats(IComparer catComparer)
        {
            var cat1 = new Cat("小猫1",1);
            var cat2 = new Cat("小猫2",2);
            if (catComparer.Compare(cat2, cat1) > 0)
            {
                Console.WriteLine("小猫2胜出");
            }
            else
            {
                Console.WriteLine("小猫1胜出");
            }
        }
    }    
复制代码

有了逆变,客户端调用MyHelper的CompareCats方法时,可以传入IComparer类型的实参。

复制代码
            IComparer animalComparer = new AnimalSizeComparator();

            MyHelper myHelper = new MyHelper();

            myHelper.CompareCats(animalComparer);

            Console.ReadKey(); 
复制代码

可见,在方法中基于派生类接口类型的形参,调用该方法的时候可以传入基类接口类型的实参。 

总结:在本篇的场景中,派生类接口替代父类接口,称之为协变;父类接口代替派生类接口,称之为逆变。

 

 

对于过长字符串的大小比对

 

嘛  事情发生是这样的 由于生成卡号太长(900038080205489 这种)  又要判断某卡号位于某个区间 再去判断机构
一开始很天真的直接按照惯性思维来写

query = query.Where(x=>x.Code>=MinCode && x.Code 
       

结果出问题了 2333

因为这里我把卡号当做int类型的去做大小判断结果报错

按理来说应该用long类型 6位数以下的两者没区别 但是超过6位就不行了

数据范围不一样
int -2^31~2^31-1
long long -2^63~^63-1

所以后期处理的办法是这样的

query = query.Where(x => x.Code.CompareTo(EndCode) >= 0 && x.Code.CompareTo(MaxCode) <= 0);

这里CompareTo是字符串的比较方法 

当a>b的时候a.CompareTo(b) == 1

当a=b的时候a.CompareTo(b) == 0

当a>b的时候a.CompareTo(b) == -1

有很多东西 我都只是暂时知道这么用可以,但是不太清楚他的底层原理 以后的日子里 我会日渐完善这些笔记之类的,也欢迎各位大佬的指导和建议 从入门到入土 我从未停下emmm....没了 再见

转载于:https://www.cnblogs.com/cjm123/p/9231340.html

你可能感兴趣的:(c#)