• .net学习之集合、foreach原理、Hashtable、Path类、File类、Directory类、文件流FileStream类、压缩流GZipStream、拷贝大文件、序列化和反序列化


    1.集合
    (1)ArrayList内部存储数据的是一个object数组,创建这个类的对象的时候,这个对象里的数组的长度为0
    (2)调用Add方法加元素的时候,如果第一次增加元神,就会将数组的长度变为4往里面加
    (3)如果存储数据的数组满了,就会新建一个数组长度是原来的数组的两倍,这个数组被原来的数组的变量所引用
    比如自己实现简单的ArrayList Add方法

    public class MyArrayList
        {
            private object[] objArray=new object[2];
            int index = 0;
            public void Add(object obj)
            {
                if (index>=objArray.Length-1)
                {
                    object[] newObjArray = new object[objArray.Length*2];
                    Array.Copy(objArray, newObjArray, objArray.Length);
                    objArray = newObjArray;
                }
                objArray[index] = obj;
                index++;
            }
            public int Count
            {
                get
                {
                    return index + 1;
                }
            }
    
            /// <summary>
            /// 索引器
            /// </summary>
            /// <param name="i"></param>
            /// <returns></returns>
            public object this[int i]
            {
                get
                {
                    return objArray[i];
                }
                set
                {
                    objArray[i] = value;
                }
            }

    (4)常用集合
    “类似数组”集合:ArrayList、List<T>
    “键值对”集合(“哈希表”集合):Hashtable、Dictionary<K,V>
    “堆栈”集合:Stack、Stack<T>(LIFO)
    “队列”集合:Queue、Queue<T>(FIFO)

    “可排序键值对”集合:(插入、检索没有“哈希表”集合高效)
    SortedList、SortedList<K,V> (占用内存更少,可以通过索引访问)
    SortedDictionary<K,V> (占用内存更多,没有索引,但插入、删除元素的速度比SortedList快)
    Set 集合:无序、不重复。HashSet<T>,可以将 HashSet类视为不包含值的 Dictionary集合。与List<T>类似。SortedSet<T>(.net4.0支持,有序无重复集合)
    “双向链表”集合:LinkedList<T>,增删速度快。

     SortedList sortedList = new SortedList();
                sortedList.Add("a", "A");
                sortedList.Add("x", "X");
                sortedList.Add("w", "W");
                sortedList.Add("b", "B");
    
                foreach (DictionaryEntry item in sortedList)
                {
                    Console.WriteLine(item.Key + "  " + item.Value);
                }
                for (int i = 0; i < sortedList.Count; i++)
                {
                    Console.WriteLine(sortedList[sortedList.GetKey(i)]);
                }

    ArrayList (非泛型)→ List<T>(泛型)
    Hashtable(非泛型) → Dictionary<K,V>(泛型)

    2.foreach原理
    如果一个类要被foreach遍历,就要实现IEnumerable接口
    比如:

    public class MyArrayList:IEnumerable
        {
            private object[] objArray=new object[2];
            int index = 0;
            public void Add(object obj)
            {
                if (index>=objArray.Length-1)
                {
                    object[] newObjArray = new object[objArray.Length*2];
                    Array.Copy(objArray, newObjArray, objArray.Length);
                    objArray = newObjArray;
                }
                objArray[index] = obj;
                index++;
            }
            public int Count
            {
                get
                {
                    return index + 1;
                }
            }
    
            /// <summary>
            /// 索引器
            /// </summary>
            /// <param name="i"></param>
            /// <returns></returns>
            public object this[int i]
            {
                get
                {
                    return objArray[i];
                }
                set
                {
                    objArray[i] = value;
                }
            }
    
            public IEnumerator GetEnumerator()
            {
                return new MyIEnumerator(objArray, Count);
            }
        }
    
        public class MyIEnumerator : IEnumerator
        {
    
            private object[] objArr;
            /// <summary>
            /// 保存的是当前读到的第几个元素,默认-1
            /// </summary>
            int index = -1;
            /// <summary>
            /// 存储在数组中元素的个数
            /// </summary>
            int count;
            public MyIEnumerator(object[] obj,int count)
            {
                this.objArr = obj;
                this.count = count;
            }
    
            /// <summary>
            /// 返回当前指针指向的元素的值
            /// </summary>
            public object Current
            {
                get { return objArr[index]; }
            }
    
            /// <summary>
            /// 将指针向前移动一位并判断当前元素有没有元素
            /// </summary>
            /// <returns></returns>
            public bool MoveNext()
            {
                index++;
                if (index<count)
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
    
            public void Reset()
            {
                throw new NotImplementedException();
            }
        }
    foreach 遍历实际上是这样的
        IEnumerator tor = list.GetEnumerator();
        while (tor.MoveNext())
        {
            Console.WriteLine(tor.Current);
        }

    3.Hashtable
    键值对是以键的hash值算出其所对应的下标,存的时候算一下下标,然后存储在下标所对应的位置,取的时候也是一样
    Hashtable中的值是存储在bucket[] buckets这个结构数组中
    bucket b = new bucket();
    b.Key="1";
    b.Value="2";
    b.hash_coll=b.Key.GetHashCode();
    int index = b.hash_coll%buckets.Lenth;
    buckets[index]=b
    存储的值的顺序是根据键的hash值算出

    4.异常处理
    int i = 1;
    try
    {

    return i;
    }
    finally
    {
    i++;
    }
    这个程序返回的值为1
    Student s = new Student();
    s.ID = 1;
    try
    {

    return s;
    }
    finally
    {
    s.ID++;
    }
    这个程序返回的值为s.ID=2

    5.Path类
    string path = @"da1.txt";
    string newPath = Path.ChangeExtension(@"d1.txt","avi");更改路径字符串的后缀名
    newPath = Path.Combine(@"d12","12.txt");合并多个字符串路径,如果没有"",自动加上
    newPath = Path.GetDirectoryName(path);得到文件路径所在的目录,如果本身就是一个目录,就直接返回这个目录字符串
    newPath = Path.GetExtension(path);得到指定文件路径的后缀名,如果不是一个文件路径,返回空字符串
    newPath = Path.GetFileName(path);得到指定路径的文件名(带后缀名)
    newPath = Path.GetFileNameWithoutExtension(path);得到指定路径的文件名(不带后缀名)
    newPath = Path.GetFullPath(path);得到绝对路径
    newPath = Path.GetTempPath();得到系统的临时目录
    newPath = Path.GetTempFileName();得到一个刚刚创建的临时的文件名
    newPath = Assembly.GetExecutingAssembly().Location得到当前运行程序集的路径

    6.File类
    string path = @"da1.txt";
    File.Create(path);创建指定的文件,如果文件已存在,则覆盖
    File.AppendAllText(path,"aaaa");向已有的文本文件中追加字符,如果文件不存在,则创建一个新的文件
    File.Copy(“source”, “targetFileName”, true);//文件拷贝,true表示当文件存在时“覆盖”,如果不加true,则文件存在报异常。
    File.Delete(path);
    File.Exists(path);
    File.Move(原路径,目标路径);
    string str = File.ReadAllText(path,Encoding.Default);读取的文件用什么编码存储就用什么编码读取,有的时候必须指定的编码
    格式
    string[] lines = File.ReadAllLines(path,Encoding.Default);读取文本文档,返回字符串数组

    7.Directory类
    Delete(string path) 删除目录,如果要递归删除 调用Delete(string path,bool recursive)
    Exists(string) 指定目录是否存在
    Move(string oldDir,string newDir) 移动目录 ----改名原理一致
    CreateDiectory() 创建目录
    string[] GetDirectories() 得到指定目录下的所有的子目录 返回string数组
    string[] GetDirectories(string path,string searchPattern,SearchOption opton) 可以按统配符查找子目录
    GetFiles() 得到指定目录下的所有的文件

    8.字符编码
    字符编码就是字符以什么样的二进制排序存入到电脑的硬盘,并按照什么样的规则读取出来并还原.
    ASCII码 GB2312 Unicode UTF-8

    9.DirectoryInfo类
    是1个操作目录的实例类,提供了与静态类Directory类相同的方法 但是做了少部分扩展
    当需要对目录进行多次操作的时候 最好是将该目录封装到实例对象中 以便多次操作

    10.FileInfo类
    是1个操作文件的实例类 提供了静态File相同的方法 但是做了扩展 比如可以得到文件的大小.....等
    当需要对同1个文件进行多次操作的时候 最好是将该文件封装到改对象中操作

    11.FileStream类
    文件的读取:
    //1.创建一个文件流对象,并给这个文件流对象指定操作的文件(路径)还有指定操作方式
    FileStream fs = new FileStream(@"e:1.txt", FileMode.Open);
    //2.准备一个byte数组,以供文件流对象读取数据并放到这个数组里面
    byte[] bytes = new byte[1024 * 1024];
    //3.调用文件流的读数据方法,将读出来的字节放入到bytes数组中
    fs.Read(bytes, 0, bytes.Length);
    //4.将字节数组以指定的编码转换为字符串
    string content = Encoding.Default.GetString(bytes);
    //5.关闭文件流
    fs.Dispose();
    推荐使用using关键字释放
    文件的写入:
    //1.创建一个文件流对象,并给这个文件流对象指定操作的文件(路径)还有指定操作方式
    FileStream fs = new FileStream(@"e:1.txt", FileMode.Create);
    //2.将要写人的文字转换为字节数组
    byte[] bytes = Encoding.Default.GetBytes("我是要写入的文字");
    //3.调用文件流的写入数据方法
    fs.Write(bytes, 0, bytes.Length);
    //4.关闭文件流
    fs.Dispose();

    拷贝大文件
    using (FileStream fsRead = new FileStream(@"e:1.wmv",FileMode.Open))
    {
    using (FileStream fsWrite = new FileStream(@"e:2.wmv", FileMode.Create))
    {
    byte[] bytes = new byte[1024 * 1024];
    int length;
    do
    {
    length = fsRead.Read(bytes, 0, bytes.Length);//length表示读取的真实的字节数,bytes.Length表示一次预读取的
    //字节数
    fsWrite.Write(bytes, 0, length);
    } while (length == bytes.Length);

    }

    12.压缩流GZipStream

    压缩原理:1.图片2.文本文件3.电影4.字符串
    1>压缩:
    1.创建读取流File.OpenRead()
    2.创建写入流File.OpenWrite();
    3.创建压缩流new GZipStream();将写入流作为参数与。
    4.每次通过读取流读取一部分数据,通过压缩流写入。
    2>解压
    1.创建读取流:File.OpenRead()
    2.创建压缩流:new GZipStream();将读取流作为参数
    3.创建写入流File.OpenWrite();
    4.每次通过压缩流读取数据,通过写入流写入数据。

    //GZipStream就是对FileStream的又一个包装
                //将文本文件1.txt压缩
                //1.创建读取文本文件的流
                using (FileStream fsRead = File.OpenRead("1.txt"))
                {
                    //2.创建写入文本文件的流
                    using (FileStream fsWrite = File.OpenWrite("yasuo.txt"))
                    {
                        //3.创建压缩流
                        using (GZipStream zipStream = new GZipStream(fsWrite, CompressionMode.Compress))
                        {
                            //4.每次读取1024byte
                            byte[] byts = new byte[1024];
                            int len = 0;
                            while ((len = fsRead.Read(byts, 0, byts.Length)) > 0)
                            {
                                //通过压缩流写入文件
                                zipStream.Write(byts, 0, len);
                            }
                        }
                    }
                }
                Console.WriteLine("ok");
                Console.ReadKey();
    
                using (FileStream fsRead = File.OpenRead("yasuo.txt"))
                {
    
                    using (GZipStream gzipStream = new GZipStream(fsRead, CompressionMode.Decompress))
                    {
                        using (FileStream fsWrite = File.OpenWrite("jieya.txt"))
                        {
    
                            byte[] byts = new byte[1024];
                            int len = 0;
                            while ((len = gzipStream.Read(byts, 0, byts.Length)) > 0)
                            {
                                fsWrite.Write(byts, 0, len);
                            }
    
                        }
                    }
                }
                Console.WriteLine("ok");
                Console.ReadKey();

    13.using
    被using管理的对象一出usin块就会自动调用这个对象的Dispose方法
    如果类的对象要被using管理,这个对象的类必须实现IDisposable接口
    using的本质就是一个try finally,将using中的代码生成在了try中,调用该对象的Dispose()写在了finally中

    14.序列化和反序列化
    序列化:将对象的状态持久化到某一种设备上(磁盘)
    要将类标记为Serializable,这个类的对象才可以被序列化
    以二进制的方式序列化,而不是文本文档
    反序列化:将之前序列化的文件还原为对象

  • 相关阅读:
    Job for docker.service failed because the control process exited with error code. See
    连接数据库出现The server time zone value '�й���׼ʱ��' is unrecogni等问题的解决方案
    【面试】SSH 框架原理
    【面试】Spring 执行流程
    【面试】Redis
    Innosetup打包自动下载.net framework 动态库及替换卸载程序图标.
    分享一个带有合计行功能的DataGridView扩展
    记录一次系统优化
    使用 Cordova(PhoneGap)构建Android程序
    分享一个换肤解决方案
  • 原文地址:https://www.cnblogs.com/yxlblogs/p/3404656.html
Copyright © 2020-2023  润新知