├── .github ├── ISSUE_TEMPLATE │ ├── bug-report.md │ └── feature-request.md └── workflows │ ├── nuget_pre.yml │ ├── nuget_prod.yml │ └── pull_request.yml ├── .gitignore ├── EasyTool.Core ├── CloneCategory │ ├── CloneExtension.cs │ └── CloneUtil.cs ├── CodeCategory │ ├── AesUtil.cs │ ├── Base32Util.cs │ ├── Base62Util.cs │ ├── Base64Util.cs │ ├── DesUtil.cs │ ├── MorseUtil.cs │ ├── PunycodeUtil.cs │ └── RotUtil.cs ├── CollectionsCategory │ ├── DictionaryExtension.cs │ ├── IteratorUtil.cs │ ├── LinkedListExtension.cs │ ├── LinkedListUtil.cs │ ├── ListExtension.cs │ ├── ListUtil.cs │ ├── QueueExtension.cs │ ├── QueueUtil.cs │ ├── StackExtension.cs │ └── StackUtil.cs ├── ConvertCategory │ ├── ConvertUtil.cs │ └── Extension.Convert.cs ├── DateTimeCategory │ ├── DateTimeExtension.cs │ ├── DateTimeUtil.cs │ ├── LunarCalendarUtil.cs │ ├── TimerUtil.cs │ └── TimestampUtil.cs ├── EasyTool.Core.csproj ├── EmojiCategory │ └── EmojiUtil.cs ├── IEnumerableCategory │ └── IEnumerableExtensions.cs ├── IOCategory │ ├── FileTypeExtension.cs │ ├── FileTypeUtil.cs │ ├── FileUtil.cs │ ├── IoUtil.cs │ ├── Tailer.cs │ └── WatchMonitor.cs ├── LanguageCategory │ ├── BCDUtil.cs │ ├── SingletonUtil.cs │ └── TreeUtil.cs ├── MathCategory │ ├── MathUtil.cs │ ├── NumberUtil.cs │ └── PredictUtil.cs ├── NetCategory │ ├── HttpClientExtension.cs │ └── NetUtil.cs ├── Standardization │ ├── Option.cs │ ├── QueryPage.cs │ └── Result.cs ├── TextCategory │ ├── CsvUtil.cs │ ├── StrSplitter.cs │ └── UnicodeUtil.cs └── ToolCategory │ ├── ArrayUtil.cs │ ├── ClassExtension.cs │ ├── ClassUtil.cs │ ├── CreditCodeUtil.cs │ ├── DLLUtil.cs │ ├── DesensitizedUtil.cs │ ├── EnumUtil.cs │ ├── EnvUtil.cs │ ├── EscapeUtil.cs │ ├── HashUtil.cs │ ├── HexUtil.cs │ ├── IdUtil.cs │ ├── IdcardUtil.cs │ ├── IpUtil.cs │ ├── MEFUtil.cs │ ├── ObjectUtil.cs │ ├── PageUtil.cs │ ├── ProcessUtil.cs │ ├── RandomUtil.cs │ ├── ReflectUtil.cs │ ├── RegexUtil.cs │ ├── RuntimeUtil.cs │ ├── SimpleMapExtension.cs │ ├── StrExtension.cs │ ├── StrUtil.cs │ ├── TypeUtil.cs │ ├── URLUtil.cs │ ├── XmlUtil.cs │ └── ZipUtil.cs ├── EasyTool.CoreTests ├── CloneCategory │ └── CloneExtensionTests.cs ├── CodeCategory │ ├── AesUtilTests.cs │ └── DesUtilTests.cs ├── EasyTool.CoreTests.csproj ├── MathCategory │ └── MathUtilTests.cs ├── Standardization │ ├── OptionTests.cs │ └── ResultTests.cs └── ToolCategory │ ├── IDUtilTests.cs │ ├── IpUtilTests.cs │ └── SimpleMapExtensionTests.cs ├── EasyTool.EmitMapper ├── EasyTool.EmitMapper.csproj └── EmitMapperCategory │ └── EmitMapperExtension.cs ├── EasyTool.EmitMapperTests ├── EasyTool.EmitMapperTests.csproj └── EmitMapperCategory │ └── EmitMapperExtensionTests.cs ├── EasyTool.Image ├── EasyTool.Image.csproj └── ImageCategory │ ├── ImgExtension.cs │ └── ImgUtil.cs ├── EasyTool.ImageTests ├── EasyTool.ImageTests.csproj └── ImageCategory │ ├── ImageUtilTests.cs │ └── Resources │ ├── mask.jpg │ ├── ori.jpg │ └── result.jpg ├── EasyTool.NPOI ├── EasyTool.NPOI.csproj ├── ExcelWorkbookType.cs └── NPOIUtil.cs ├── EasyTool.NPOITests ├── EasyTool.NPOITests.csproj └── NPOIUtilTests.cs ├── EasyTool.Web ├── DevelopmentCategory │ ├── BuildDtoToTS.cs │ ├── BuildOptionToTS.cs │ └── BuildWebApiToTS.cs └── EasyTool.Web.csproj ├── EasyTool.WebTests ├── DevelopmentCategory │ ├── BuildDtoToTSTests.cs │ ├── BuildOptionToTSTests.cs │ └── BuildWebApiToTSTests.cs └── EasyTool.WebTests.csproj ├── EasyTool.sln ├── LICENSE ├── README.EN-US.md ├── README.md └── logo.png /.github/ISSUE_TEMPLATE/bug-report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: "Bug Report 🐛" 3 | about: 这里只能提交 Bug,提交其他无关信息会被关闭 4 | title: '' 5 | labels: Bug 6 | assignees: '' 7 | --- 8 | 9 | 14 | 15 | #### 问题描述及重现代码: 16 | 17 | ```c# 18 | // c# code 19 | ``` 20 | 21 | #### 具体版本 22 | 23 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature-request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: "Feature Request 🚀" 3 | about: 这里只能提交 Feature 请求,提交其他无关信息会被关闭 4 | title: '' 5 | labels: Feature 6 | assignees: '' 7 | --- 8 | 9 | 15 | 16 | #### Feature 特性 17 | 18 | ```c# 19 | // c# code 20 | ``` 21 | 22 | #### 简要描述原因 23 | 24 | 25 | 26 | #### 使用场景 27 | 28 | ```c# 29 | // c# code 30 | ``` -------------------------------------------------------------------------------- /.github/workflows/nuget_pre.yml: -------------------------------------------------------------------------------- 1 | # This workflow will build a .NET project 2 | # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-net 3 | 4 | name: nuget_pre 5 | 6 | on: 7 | push: 8 | branches: [ main ] 9 | 10 | jobs: 11 | build: 12 | 13 | runs-on: ubuntu-latest 14 | 15 | steps: 16 | - uses: actions/checkout@v3 17 | - name: Setup .NET 18 | uses: actions/setup-dotnet@v3 19 | with: 20 | dotnet-version: 6.0.x 21 | - name: Restore dependencies 22 | run: dotnet restore 23 | - name: Build 24 | run: dotnet build --no-restore 25 | - name: Test 26 | run: dotnet test --no-build --verbosity normal 27 | - name: Package Nuget 📦 28 | run: | 29 | dotnet build -c Release "EasyTool.Core/EasyTool.Core.csproj" 30 | SUFFIX=`date "+%y%m%d%H%M%S"` 31 | dotnet pack "EasyTool.Core/EasyTool.Core.csproj" /p:PackageVersion=${{vars.VERSION}}-pre-${SUFFIX} -c Release -o publish --no-build --no-restore 32 | - name: Publish to Nuget ✔ 33 | run: | 34 | dotnet nuget push publish/*.nupkg -s https://api.nuget.org/v3/index.json -k ${{secrets.NUGET_API_KEY}} --skip-duplicate 35 | -------------------------------------------------------------------------------- /.github/workflows/nuget_prod.yml: -------------------------------------------------------------------------------- 1 | # This workflow will build a .NET project 2 | # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-net 3 | 4 | name: nuget_prod 5 | 6 | on: 7 | release: 8 | types: [published] 9 | 10 | jobs: 11 | build: 12 | 13 | runs-on: ubuntu-latest 14 | 15 | steps: 16 | - uses: actions/checkout@v3 17 | - name: Setup .NET 18 | uses: actions/setup-dotnet@v3 19 | with: 20 | dotnet-version: 6.0.x 21 | - name: Restore dependencies 22 | run: dotnet restore 23 | - name: Build 24 | run: dotnet build --no-restore 25 | - name: Test 26 | run: dotnet test --no-build --verbosity normal 27 | - name: Package Nuget 📦 28 | run: | 29 | dotnet build -c Release "EasyTool.Core/EasyTool.Core.csproj" 30 | SUFFIX=`date "+%y%m%d%H%M%S"` 31 | dotnet pack "EasyTool.Core/EasyTool.Core.csproj" /p:PackageVersion=${{vars.VERSION}} -c Release -o publish --no-build --no-restore 32 | - name: Publish to Nuget ✔ 33 | run: | 34 | dotnet nuget push publish/*.nupkg -s https://api.nuget.org/v3/index.json -k ${{secrets.NUGET_API_KEY}} --skip-duplicate 35 | -------------------------------------------------------------------------------- /.github/workflows/pull_request.yml: -------------------------------------------------------------------------------- 1 | # This workflow will build a .NET project 2 | # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-net 3 | 4 | name: pull_request 5 | 6 | on: 7 | pull_request: 8 | branches: [ "main" ] 9 | 10 | jobs: 11 | build: 12 | 13 | runs-on: ubuntu-latest 14 | 15 | steps: 16 | - uses: actions/checkout@v3 17 | - name: Setup .NET 18 | uses: actions/setup-dotnet@v3 19 | with: 20 | dotnet-version: 6.0.x 21 | - name: Restore dependencies 22 | run: dotnet restore 23 | - name: Build 24 | run: dotnet build --no-restore 25 | - name: Test 26 | run: dotnet test --no-build --verbosity normal 27 | -------------------------------------------------------------------------------- /EasyTool.Core/CloneCategory/CloneExtension.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace EasyTool.Extension 6 | { 7 | public static class CloneExtension 8 | { 9 | //定义一个泛型方法,接受一个泛型参数 T,并返回一个 T 类型的对象 10 | public static T Clone(this T obj)=> CloneUtil.Clone(obj); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /EasyTool.Core/CloneCategory/CloneUtil.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Runtime.Serialization.Formatters.Binary; 4 | using System.Runtime.Serialization; 5 | using System.Threading.Tasks; 6 | 7 | namespace EasyTool 8 | { 9 | /// 10 | /// 静态工具类 CloneHelper,用于深度克隆对象 11 | /// 12 | public static class CloneUtil 13 | { 14 | // 定义一个泛型方法,接受一个泛型参数 T,并返回一个 T 类型的对象 15 | public static T Clone(T obj) 16 | { 17 | // 检查类型是否可序列化 18 | if (!typeof(T).IsSerializable) 19 | { 20 | throw new ArgumentException("The type must be serializable.", nameof(obj)); 21 | } 22 | 23 | // 如果对象为 null,则返回 null 24 | if (ReferenceEquals(obj, null)) 25 | { 26 | return default(T); 27 | } 28 | 29 | // 创建一个二进制序列化器 30 | IFormatter formatter = new BinaryFormatter(); 31 | 32 | // 创建一个内存流 33 | using (var stream = new MemoryStream()) 34 | { 35 | // 使用二进制序列化将对象写入内存流 36 | formatter.Serialize(stream, obj); 37 | 38 | // 将内存流位置重置为开头 39 | stream.Seek(0, SeekOrigin.Begin); 40 | 41 | // 使用反序列化从内存流中读取并返回克隆的对象 42 | return (T)formatter.Deserialize(stream); 43 | } 44 | } 45 | 46 | /// 47 | /// 静态工具类 CloneHelper,用于异步深度克隆对象 48 | /// 49 | /// 50 | /// 51 | /// 52 | /// 53 | public static async Task CloneAsync(T obj) 54 | { 55 | // 检查类型是否可序列化 56 | if (!typeof(T).IsSerializable) 57 | { 58 | throw new ArgumentException("The type must be serializable.", nameof(obj)); 59 | } 60 | 61 | // 如果对象为 null,则返回 null 62 | if (ReferenceEquals(obj, null)) 63 | { 64 | return default(T); 65 | } 66 | 67 | // 创建一个二进制序列化器 68 | IFormatter formatter = new BinaryFormatter(); 69 | 70 | // 创建一个内存流 71 | using (var stream = new MemoryStream()) 72 | { 73 | // 使用二进制序列化将对象写入内存流 74 | formatter.Serialize(stream, obj); 75 | 76 | // 将内存流位置重置为开头 77 | stream.Seek(0, SeekOrigin.Begin); 78 | 79 | // 使用反序列化从内存流中读取并返回克隆的对象 80 | return (T)formatter.Deserialize(stream); 81 | } 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /EasyTool.Core/CodeCategory/Base32Util.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace EasyTool 6 | { 7 | /// 8 | /// Base32 编码解码工具类 9 | /// 10 | public static class Base32Util 11 | { 12 | // Base32 字符集,共 32 个字符 13 | private static readonly char[] BASE32_CHARS = 14 | "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567".ToCharArray(); 15 | 16 | // Base32 填充字符 17 | private const char BASE32_PADDING_CHAR = '='; 18 | 19 | /// 20 | /// 将给定的字节数组转换为 Base32 编码字符串。 21 | /// 22 | /// 要转换的字节数组 23 | /// 转换后的 Base32 编码字符串 24 | public static string Encode(byte[] bytes) 25 | { 26 | if (bytes == null) 27 | { 28 | throw new ArgumentNullException(nameof(bytes)); 29 | } 30 | 31 | int length = bytes.Length; 32 | if (length == 0) 33 | { 34 | return string.Empty; 35 | } 36 | 37 | char[] chars = new char[(length + 4) / 5 * 8]; 38 | int index = 0; 39 | for (int i = 0; i < length; i += 5) 40 | { 41 | int val = (bytes[i] << 24) + ((i + 1 < length ? bytes[i + 1] : 0) << 16) + 42 | ((i + 2 < length ? bytes[i + 2] : 0) << 8) + ((i + 3 < length ? bytes[i + 3] : 0) << 0); 43 | chars[index++] = BASE32_CHARS[(val >> 35) & 0x1F]; 44 | chars[index++] = BASE32_CHARS[(val >> 30) & 0x1F]; 45 | chars[index++] = BASE32_CHARS[(val >> 25) & 0x1F]; 46 | chars[index++] = BASE32_CHARS[(val >> 20) & 0x1F]; 47 | chars[index++] = BASE32_CHARS[(val >> 15) & 0x1F]; 48 | chars[index++] = BASE32_CHARS[(val >> 10) & 0x1F]; 49 | chars[index++] = BASE32_CHARS[(val >> 5) & 0x1F]; 50 | chars[index++] = BASE32_CHARS[val & 0x1F]; 51 | } 52 | 53 | // 添加填充字符 54 | int paddingCount = length % 5; 55 | if (paddingCount > 0) 56 | { 57 | chars[chars.Length - 1] = BASE32_PADDING_CHAR; 58 | if (paddingCount == 1) 59 | { 60 | chars[chars.Length - 2] = BASE32_PADDING_CHAR; 61 | } 62 | if (paddingCount <= 2) 63 | { 64 | chars[chars.Length - 3] = BASE32_PADDING_CHAR; 65 | } 66 | if (paddingCount <= 3) 67 | { 68 | chars[chars.Length - 4] = BASE32_PADDING_CHAR; 69 | } 70 | if (paddingCount <= 4) 71 | { 72 | chars[chars.Length - 5] = BASE32_PADDING_CHAR; 73 | } 74 | } 75 | 76 | return new string(chars); 77 | } 78 | 79 | /// 80 | /// 将给定的 Base32 编码字符串转换为字节数组。 81 | /// 82 | /// 要转换的 Base32 编码字符串 83 | /// 转换后的字节数组 84 | public static byte[] Decode(string str) 85 | { 86 | if (string.IsNullOrEmpty(str)) 87 | { 88 | throw new ArgumentException("String is null or empty.", nameof(str)); 89 | } 90 | 91 | int length = str.Length; 92 | if (length % 8 != 0) 93 | { 94 | throw new ArgumentException("Invalid length of input string: " + length, nameof(str)); 95 | } 96 | 97 | int paddingCount = 0; 98 | if (length > 0 && str[length - 1] == BASE32_PADDING_CHAR) 99 | { 100 | paddingCount++; 101 | } 102 | if (length > 1 && str[length - 2] == BASE32_PADDING_CHAR) 103 | { 104 | paddingCount++; 105 | } 106 | if (length > 3 && str[length - 3] == BASE32_PADDING_CHAR) 107 | { 108 | paddingCount++; 109 | } 110 | if (length > 4 && str[length - 4] == BASE32_PADDING_CHAR) 111 | { 112 | paddingCount++; 113 | } 114 | if (length > 6 && str[length - 6] == BASE32_PADDING_CHAR) 115 | { 116 | paddingCount++; 117 | } 118 | 119 | byte[] bytes = new byte[length / 8 * 5 - paddingCount]; 120 | int index = 0; 121 | for (int i = 0; i < length; i += 8) 122 | { 123 | int val = (DecodeBase32Char(str[i]) << 35) + 124 | (DecodeBase32Char(str[i + 1]) << 30) + 125 | (DecodeBase32Char(str[i + 2]) << 25) + 126 | (DecodeBase32Char(str[i + 3]) << 20) + 127 | (DecodeBase32Char(str[i + 4]) << 15) + 128 | (DecodeBase32Char(str[i + 5]) << 10) + 129 | (DecodeBase32Char(str[i + 6]) << 5) + 130 | DecodeBase32Char(str[i + 7]); 131 | bytes[index++] = (byte)(val >> 24); 132 | if (index < bytes.Length) 133 | { 134 | bytes[index++] = (byte)(val >> 16); 135 | } 136 | if (index < bytes.Length) 137 | { 138 | bytes[index++] = (byte)(val >> 8); 139 | } 140 | if (index < bytes.Length) 141 | { 142 | bytes[index++] = (byte)val; 143 | } 144 | } 145 | 146 | return bytes; 147 | } 148 | 149 | // 解码 Base32 字符 150 | private static int DecodeBase32Char(char c) 151 | { 152 | if (c >= 'A' && c <= 'Z') 153 | { 154 | return c - 'A'; 155 | } 156 | if (c >= '2' && c <= '7') 157 | { 158 | return c - '2' + 26; 159 | } 160 | throw new ArgumentException("Invalid character in input string: " + c, nameof(c)); 161 | } 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /EasyTool.Core/CodeCategory/Base62Util.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace EasyTool 6 | { 7 | /// 8 | /// Base62 编码解码工具类 9 | /// 10 | public static class Base62Util 11 | { 12 | // Base62 字符集,共 62 个字符 13 | private static readonly char[] BASE62_CHARS = 14 | "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".ToCharArray(); 15 | 16 | /// 17 | /// 将给定的整数转换为 Base62 编码字符串。 18 | /// 19 | /// 要转换的整数 20 | /// 转换后的 Base62 编码字符串 21 | public static string Encode(long number) 22 | { 23 | if (number < 0) 24 | { 25 | throw new ArgumentOutOfRangeException(nameof(number), "Number must be non-negative."); 26 | } 27 | 28 | if (number == 0) 29 | { 30 | return BASE62_CHARS[0].ToString(); 31 | } 32 | 33 | List chars = new List(); 34 | int targetBase = BASE62_CHARS.Length; 35 | while (number > 0) 36 | { 37 | int index = (int)(number % targetBase); 38 | chars.Add(BASE62_CHARS[index]); 39 | number = number / targetBase; 40 | } 41 | chars.Reverse(); 42 | return new string(chars.ToArray()); 43 | } 44 | 45 | /// 46 | /// 将给定的 Base62 编码字符串转换为整数。 47 | /// 48 | /// 要转换的 Base62 编码字符串 49 | /// 转换后的整数 50 | public static long Decode(string str) 51 | { 52 | if (string.IsNullOrEmpty(str)) 53 | { 54 | throw new ArgumentException("String is null or empty.", nameof(str)); 55 | } 56 | 57 | long result = 0; 58 | int sourceBase = BASE62_CHARS.Length; 59 | long multiplier = 1; 60 | for (int i = str.Length - 1; i >= 0; i--) 61 | { 62 | int digit = Array.IndexOf(BASE62_CHARS, str[i]); 63 | if (digit == -1) 64 | { 65 | throw new ArgumentException("Invalid character in string: " + str[i], nameof(str)); 66 | } 67 | result += digit * multiplier; 68 | multiplier *= sourceBase; 69 | } 70 | return result; 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /EasyTool.Core/CodeCategory/Base64Util.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace EasyTool 6 | { 7 | /// 8 | /// Base64 编码解码工具类 9 | /// 10 | public static class Base64Util 11 | { 12 | // Base64 字符集,共 64 个字符 13 | private static readonly char[] BASE64_CHARS = 14 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".ToCharArray(); 15 | 16 | // Base64 填充字符 17 | private const char BASE64_PADDING_CHAR = '='; 18 | 19 | /// 20 | /// 将给定的字节数组转换为 Base64 编码字符串。 21 | /// 22 | /// 要转换的字节数组 23 | /// 转换后的 Base64 编码字符串 24 | public static string Encode(byte[] bytes) 25 | { 26 | if (bytes == null) 27 | { 28 | throw new ArgumentNullException(nameof(bytes)); 29 | } 30 | 31 | int length = bytes.Length; 32 | if (length == 0) 33 | { 34 | return string.Empty; 35 | } 36 | 37 | char[] chars = new char[(length + 2) / 3 * 4]; 38 | int index = 0; 39 | for (int i = 0; i < length; i += 3) 40 | { 41 | int val = (bytes[i] << 16) + ((i + 1 < length ? bytes[i + 1] : 0) << 8) + (i + 2 < length ? bytes[i + 2] : 0); 42 | chars[index++] = BASE64_CHARS[(val >> 18) & 0x3F]; 43 | chars[index++] = BASE64_CHARS[(val >> 12) & 0x3F]; 44 | chars[index++] = BASE64_CHARS[(val >> 6) & 0x3F]; 45 | chars[index++] = BASE64_CHARS[val & 0x3F]; 46 | } 47 | 48 | // 添加填充字符 49 | int paddingCount = length % 3; 50 | if (paddingCount > 0) 51 | { 52 | chars[chars.Length - 1] = BASE64_PADDING_CHAR; 53 | if (paddingCount == 1) 54 | { 55 | chars[chars.Length - 2] = BASE64_PADDING_CHAR; 56 | } 57 | } 58 | 59 | return new string(chars); 60 | } 61 | 62 | /// 63 | /// 将给定的 Base64 编码字符串转换为字节数组。 64 | /// 65 | /// 要转换的 Base64 编码字符串 66 | /// 转换后的字节数组 67 | public static byte[] Decode(string str) 68 | { 69 | if (string.IsNullOrEmpty(str)) 70 | { 71 | throw new ArgumentException("String is null or empty.", nameof(str)); 72 | } 73 | int length = str.Length; 74 | if (length % 4 != 0) 75 | { 76 | throw new ArgumentException("Invalid length of input string: " + length, nameof(str)); 77 | } 78 | 79 | int paddingCount = 0; 80 | if (length > 0 && str[length - 1] == BASE64_PADDING_CHAR) 81 | { 82 | paddingCount++; 83 | } 84 | if (length > 1 && str[length - 2] == BASE64_PADDING_CHAR) 85 | { 86 | paddingCount++; 87 | } 88 | 89 | byte[] bytes = new byte[length / 4 * 3 - paddingCount]; 90 | int index = 0; 91 | for (int i = 0; i < length; i += 4) 92 | { 93 | int val = (DecodeBase64Char(str[i]) << 18) + 94 | (DecodeBase64Char(str[i + 1]) << 12) + 95 | (DecodeBase64Char(str[i + 2]) << 6) + 96 | DecodeBase64Char(str[i + 3]); 97 | bytes[index++] = (byte)(val >> 16); 98 | if (index < bytes.Length) 99 | { 100 | bytes[index++] = (byte)(val >> 8); 101 | } 102 | if (index < bytes.Length) 103 | { 104 | bytes[index++] = (byte)val; 105 | } 106 | } 107 | 108 | return bytes; 109 | } 110 | 111 | // 解码 Base64 字符 112 | private static int DecodeBase64Char(char c) 113 | { 114 | if (c >= 'A' && c <= 'Z') 115 | { 116 | return c - 'A'; 117 | } 118 | if (c >= 'a' && c <= 'z') 119 | { 120 | return c - 'a' + 26; 121 | } 122 | if (c >= '0' && c <= '9') 123 | { 124 | return c - '0' + 52; 125 | } 126 | if (c == '+') 127 | { 128 | return 62; 129 | } 130 | if (c == '/') 131 | { 132 | return 63; 133 | } 134 | throw new ArgumentException("Invalid character in input string: " + c, nameof(c)); 135 | } 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /EasyTool.Core/CodeCategory/DesUtil.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Security.Cryptography; 6 | using System.Text; 7 | 8 | namespace EasyTool.CodeCategory 9 | { 10 | /// 11 | /// DES工具类 12 | /// 13 | public static class DesUtil 14 | { 15 | /// 16 | /// des 加密 17 | /// 18 | /// 待加密字符串 19 | /// 秘钥 20 | /// 21 | /// 22 | /// 23 | /// 24 | public static string Encrypt(string str, string sk, CipherMode cipher = CipherMode.ECB, PaddingMode padding = PaddingMode.PKCS7, Encoding? encoding = null) 25 | { 26 | if (string.IsNullOrWhiteSpace(str)) return string.Empty; 27 | if (!IsLegalSize(sk)) throw new ArgumentException("不合规的秘钥,请确认秘钥为8位的字符"); 28 | encoding ??= Encoding.UTF8; 29 | byte[] keyBytes = encoding.GetBytes(sk).ToArray(); 30 | byte[] toEncrypt = encoding.GetBytes(str); 31 | var des = DES.Create(); 32 | des.Mode = cipher; 33 | des.Padding = padding; 34 | des.Key = keyBytes; 35 | des.IV = keyBytes; 36 | 37 | ICryptoTransform cTransform = des.CreateEncryptor(); 38 | var resultArray = cTransform.TransformFinalBlock(toEncrypt, 0, toEncrypt.Length); 39 | return Convert.ToBase64String(resultArray); 40 | } 41 | 42 | /// 43 | /// Des 解密 44 | /// 45 | /// 待解密字符串 46 | /// 秘钥 47 | /// 48 | /// 49 | /// 50 | /// 51 | public static string Decrypt(string str, string sk, CipherMode cipher = CipherMode.ECB, PaddingMode padding = PaddingMode.PKCS7, Encoding? encoding = null) 52 | { 53 | if (string.IsNullOrWhiteSpace(str)) return string.Empty; 54 | if (!IsLegalSize(sk)) throw new ArgumentException("不合规的秘钥,请确认秘钥为8位的字符"); 55 | encoding ??= Encoding.UTF8; 56 | byte[] keyBytes = encoding.GetBytes(sk).ToArray(); 57 | byte[] toDecrypt = Convert.FromBase64String(str); 58 | var des = DES.Create(); 59 | des.Mode = cipher; 60 | des.Padding = padding; 61 | des.Key = keyBytes; 62 | des.IV = keyBytes; 63 | ICryptoTransform cTransform = des.CreateDecryptor(); 64 | var resultArray = cTransform.TransformFinalBlock(toDecrypt, 0, toDecrypt.Length); 65 | return encoding.GetString(resultArray); 66 | } 67 | 68 | 69 | 70 | /// 71 | /// des 加密 72 | /// 73 | /// 待加密字符串 74 | /// 秘钥 75 | /// 向量Iv 76 | /// 默认ECB 77 | /// 默认PKCS7 78 | /// 默认UTF8 79 | /// 80 | /// 81 | public static string Encrypt(string str, string sk,string iv, CipherMode cipher = CipherMode.ECB, PaddingMode padding = PaddingMode.PKCS7, Encoding? encoding = null) 82 | { 83 | if (string.IsNullOrWhiteSpace(str)) return string.Empty; 84 | if (!IsLegalSize(sk)) throw new ArgumentException("不合规的秘钥,请确认秘钥为8位的字符"); 85 | if (!IsLegalSize(iv)) throw new ArgumentException("不合规的IV,请确认IV为8位的字符"); 86 | encoding ??= Encoding.UTF8; 87 | byte[] keyBytes = encoding.GetBytes(sk).ToArray(); 88 | byte[] toEncrypt = encoding.GetBytes(str); 89 | var des = DES.Create(); 90 | des.Mode = cipher; 91 | des.Padding = padding; 92 | des.Key = keyBytes; 93 | des.IV = keyBytes; 94 | 95 | ICryptoTransform cTransform = des.CreateEncryptor(); 96 | var resultArray = cTransform.TransformFinalBlock(toEncrypt, 0, toEncrypt.Length); 97 | return Convert.ToBase64String(resultArray); 98 | } 99 | 100 | /// 101 | /// Des 解密 102 | /// 103 | /// 待解密字符串 104 | /// 秘钥 105 | /// 向量Iv 106 | /// 默认ECB 107 | /// 默认PKCS7 108 | /// 默认UTF8 109 | /// 110 | /// 111 | public static string Decrypt(string str, string sk, string iv, CipherMode cipher = CipherMode.ECB, PaddingMode padding = PaddingMode.PKCS7, Encoding? encoding = null) 112 | { 113 | if (string.IsNullOrWhiteSpace(str)) return string.Empty; 114 | if (!IsLegalSize(sk)) throw new ArgumentException("不合规的秘钥,请确认秘钥为8位的字符"); 115 | if (!IsLegalSize(iv)) throw new ArgumentException("不合规的IV,请确认IV为8位的字符"); 116 | encoding ??= Encoding.UTF8; 117 | byte[] keyBytes = encoding.GetBytes(sk).ToArray(); 118 | byte[] toDecrypt = Convert.FromBase64String(str); 119 | var des = DES.Create(); 120 | des.Mode = cipher; 121 | des.Padding = padding; 122 | des.Key = keyBytes; 123 | des.IV = keyBytes; 124 | ICryptoTransform cTransform = des.CreateDecryptor(); 125 | var resultArray = cTransform.TransformFinalBlock(toDecrypt, 0, toDecrypt.Length); 126 | return encoding.GetString(resultArray); 127 | } 128 | 129 | private static bool IsLegalSize(string sk) 130 | { 131 | if (!string.IsNullOrEmpty(sk) && sk.Length == 8) 132 | return true; 133 | 134 | return false; 135 | } 136 | 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /EasyTool.Core/CodeCategory/MorseUtil.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace EasyTool 6 | { 7 | /// 8 | /// Morse 电码工具类 9 | /// 10 | public static class MorseUtil 11 | { 12 | // Morse 电码表 13 | private static readonly Dictionary MORSE_TABLE = new Dictionary() 14 | { 15 | {'A', ".-"}, 16 | {'B', "-..."}, 17 | {'C', "-.-."}, 18 | {'D', "-.."}, 19 | {'E', "."}, 20 | {'F', "..-."}, 21 | {'G', "--."}, 22 | {'H', "...."}, 23 | {'I', ".."}, 24 | {'J', ".---"}, 25 | {'K', "-.-"}, 26 | {'L', ".-.."}, 27 | {'M', "--"}, 28 | {'N', "-."}, 29 | {'O', "---"}, 30 | {'P', ".--."}, 31 | {'Q', "--.-"}, 32 | {'R', ".-."}, 33 | {'S', "..."}, 34 | {'T', "-"}, 35 | {'U', "..-"}, 36 | {'V', "...-"}, 37 | {'W', ".--"}, 38 | {'X', "-..-"}, 39 | {'Y', "-.--"}, 40 | {'Z', "--.."}, 41 | {'0', "-----"}, 42 | {'1', ".----"}, 43 | {'2', "..---"}, 44 | {'3', "...--"}, 45 | {'4', "....-"}, 46 | {'5', "....."}, 47 | {'6', "-...."}, 48 | {'7', "--..."}, 49 | {'8', "---.."}, 50 | {'9', "----."}, 51 | {' ', " "} 52 | }; 53 | 54 | /// 55 | /// 将给定的字符串转换为 Morse 电码字符串。 56 | /// 57 | /// 要转换的字符串 58 | /// 转换后的 Morse 电码字符串 59 | public static string Encode(string str) 60 | { 61 | if (string.IsNullOrEmpty(str)) 62 | { 63 | return string.Empty; 64 | } 65 | 66 | List morseCodes = new List(); 67 | foreach (char c in str.ToUpper()) 68 | { 69 | if (MORSE_TABLE.ContainsKey(c)) 70 | { 71 | morseCodes.Add(MORSE_TABLE[c]); 72 | } 73 | } 74 | return string.Join(" ", morseCodes); 75 | } 76 | 77 | 78 | /// 79 | /// 将给定的 Morse 电码字符串转换为原始字符串。 80 | /// 81 | /// 要转换的 Morse 电码字符串 82 | /// 转换后的原始字符串 83 | public static string Decode(string morseCode) 84 | { 85 | if (string.IsNullOrEmpty(morseCode)) 86 | { 87 | return string.Empty; 88 | } 89 | 90 | string[] codes = morseCode.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); 91 | List chars = new List(); 92 | foreach (string code in codes) 93 | { 94 | foreach (KeyValuePair kvp in MORSE_TABLE) 95 | { 96 | if (kvp.Value == code) 97 | { 98 | chars.Add(kvp.Key); 99 | break; 100 | } 101 | } 102 | } 103 | return new string(chars.ToArray()); 104 | } 105 | 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /EasyTool.Core/CodeCategory/RotUtil.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace EasyTool 7 | { 8 | /// 9 | /// ROT 工具类 10 | /// 11 | public static class RotUtil 12 | { 13 | /// 14 | /// 将给定的字符串按照 ROT 加密算法进行加密。 15 | /// 16 | /// 要加密的字符串 17 | /// 偏移量 18 | /// 加密后的字符串 19 | public static string Encrypt(string text, int n) 20 | { 21 | if (string.IsNullOrEmpty(text)) 22 | { 23 | return text; 24 | } 25 | 26 | string upperCaseText = text.ToUpper(); 27 | return new string(upperCaseText.Select(c => 28 | { 29 | if (!char.IsLetter(c)) 30 | { 31 | return c; 32 | } 33 | 34 | int x = c - 'A'; 35 | int y = (x + n) % 26; 36 | return (char)(y + 'A'); 37 | }).ToArray()); 38 | } 39 | 40 | /// 41 | /// 将给定的字符串按照 ROT 加密算法进行解密。 42 | /// 43 | /// 要解密的字符串 44 | /// 偏移量 45 | /// 解密后的字符串 46 | public static string Decrypt(string text, int n) 47 | { 48 | return Encrypt(text, 26 - n); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /EasyTool.Core/CollectionsCategory/DictionaryExtension.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace EasyTool.Extension 7 | { 8 | public static class DictionaryExtension 9 | { 10 | /// 11 | /// 获取字典中指定键的值,如果字典中不存在该键,则返回默认值 12 | /// 13 | /// 要获取值的字典 14 | /// 要获取值的键 15 | /// 如果字典中不存在该键,则返回的默认值 16 | /// 指定键的值,如果字典中不存在该键,则返回默认值 17 | public static TValue GetValueOrDefault(this IDictionary dictionary, TKey key, TValue defaultValue = default) 18 | { 19 | if (dictionary.TryGetValue(key, out TValue value)) 20 | { 21 | return value; 22 | } 23 | 24 | return defaultValue; 25 | } 26 | 27 | /// 28 | /// 将一个字典的所有键值对添加到另一个字典中 29 | /// 30 | /// 要添加键值对的目标字典 31 | /// 包含要添加键值对的源字典 32 | public static void AddRange(this IDictionary destination, IDictionary source) 33 | { 34 | if (source == null) 35 | { 36 | throw new ArgumentNullException(nameof(source)); 37 | } 38 | 39 | foreach (KeyValuePair pair in source) 40 | { 41 | destination[pair.Key] = pair.Value; 42 | } 43 | } 44 | 45 | /// 46 | /// 返回字典中键的集合 47 | /// 48 | /// 要获取键的字典 49 | /// 字典中所有键的集合 50 | public static IEnumerable GetKeys(this IDictionary dictionary) 51 | { 52 | return dictionary.Keys; 53 | } 54 | 55 | /// 56 | /// 返回字典中值的集合 57 | /// 58 | /// 要获取值的字典 59 | /// 字典中所有值的集合 60 | public static IEnumerable GetValues(this IDictionary dictionary) 61 | { 62 | return dictionary.Values; 63 | } 64 | 65 | /// 66 | /// 从字典中删除指定的键 67 | /// 68 | /// 要删除键的字典 69 | /// 要删除的键的集合 70 | public static void RemoveKeys(this IDictionary dictionary, IEnumerable keys) 71 | { 72 | if (keys == null) 73 | { 74 | throw new ArgumentNullException(nameof(keys)); 75 | } 76 | foreach (TKey key in keys) 77 | { 78 | dictionary.Remove(key); 79 | } 80 | } 81 | 82 | /// 83 | /// 返回字典中具有最大值的键 84 | /// 85 | /// 要查找键的字典 86 | /// 具有最大值的键 87 | public static TKey GetKeyWithMaxValue(this IDictionary dictionary) where TValue : IComparable 88 | { 89 | if (dictionary.Count == 0) 90 | { 91 | throw new InvalidOperationException("The dictionary is empty."); 92 | } 93 | 94 | KeyValuePair max = dictionary.First(); 95 | 96 | foreach (KeyValuePair pair in dictionary) 97 | { 98 | if (pair.Value.CompareTo(max.Value) > 0) 99 | { 100 | max = pair; 101 | } 102 | } 103 | 104 | return max.Key; 105 | } 106 | 107 | /// 108 | /// 返回字典中具有最小值的键 109 | /// 110 | /// 要查找键的字典 111 | /// 具有最小值的键 112 | public static TKey GetKeyWithMinValue(this IDictionary dictionary) where TValue : IComparable 113 | { 114 | if (dictionary.Count == 0) 115 | { 116 | throw new InvalidOperationException("The dictionary is empty."); 117 | } 118 | 119 | KeyValuePair min = dictionary.First(); 120 | 121 | foreach (KeyValuePair pair in dictionary) 122 | { 123 | if (pair.Value.CompareTo(min.Value) < 0) 124 | { 125 | min = pair; 126 | } 127 | } 128 | 129 | return min.Key; 130 | } 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /EasyTool.Core/CollectionsCategory/LinkedListExtension.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace EasyTool.Extension 6 | { 7 | 8 | /// 9 | /// 双向链表工具类 10 | /// 11 | public static class LinkedListExtension 12 | { 13 | /// 14 | /// 将双向链表中的某个节点移动到链表的结尾处。 15 | /// 16 | /// 双向链表元素类型 17 | /// 双向链表 18 | /// 要移动的节点 19 | public static void MoveLast(this LinkedList list, LinkedListNode node) => LinkedListUtil.MoveLast(list,node); 20 | 21 | /// 22 | /// 将双向链表中移动到最前方 23 | /// 24 | /// 双向链表元素类型 25 | /// 双向链表 26 | /// 要移动的节点 27 | public static void MoveFirst(this LinkedList list, LinkedListNode node) => LinkedListUtil.MoveFirst(list,node); 28 | 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /EasyTool.Core/CollectionsCategory/LinkedListUtil.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace EasyTool 6 | { 7 | /// 8 | /// 双向链表工具类 9 | /// 10 | public class LinkedListUtil 11 | { 12 | /// 13 | /// 将指定元素添加到双向链表的结尾处。 14 | /// 15 | /// 双向链表元素类型 16 | /// 双向链表 17 | /// 要添加的元素 18 | public static void AddLast(LinkedList list, T item) 19 | { 20 | list.AddLast(item); 21 | } 22 | 23 | /// 24 | /// 将指定元素添加到双向链表的开头处。 25 | /// 26 | /// 双向链表元素类型 27 | /// 双向链表 28 | /// 要添加的元素 29 | public static void AddFirst(LinkedList list, T item) 30 | { 31 | list.AddFirst(item); 32 | } 33 | 34 | /// 35 | /// 将指定元素插入到双向链表中的指定位置之前。 36 | /// 37 | /// 双向链表元素类型 38 | /// 双向链表 39 | /// 要在其前面插入新元素的节点 40 | /// 要添加的元素 41 | /// 新节点 42 | public static LinkedListNode AddBefore(LinkedList list, LinkedListNode node, T item) 43 | { 44 | return list.AddBefore(node, item); 45 | } 46 | 47 | /// 48 | /// 将指定元素插入到双向链表中的指定位置之后。 49 | /// 50 | /// 双向链表元素类型 51 | /// 双向链表 52 | /// 要在其后面插入新元素的节点 53 | /// 要添加的元素 54 | /// 新节点 55 | public static LinkedListNode AddAfter(LinkedList list, LinkedListNode node, T item) 56 | { 57 | return list.AddAfter(node, item); 58 | } 59 | 60 | /// 61 | /// 将双向链表中的某个节点移动到链表的结尾处。 62 | /// 63 | /// 双向链表元素类型 64 | /// 双向链表 65 | /// 要移动的节点 66 | public static void MoveLast(LinkedList list, LinkedListNode node) 67 | { 68 | list.Remove(node); 69 | list.AddLast(node); 70 | } 71 | 72 | 73 | /// 74 | /// 将双向链表中移动到最前方 75 | /// 76 | /// 双向链表元素类型 77 | /// 双向链表 78 | /// 要移动的节点 79 | public static void MoveFirst(LinkedList list, LinkedListNode node) 80 | { 81 | list.Remove(node); 82 | list.AddFirst(node); 83 | } 84 | 85 | /// 86 | /// 从双向链表中移除指定节点。 87 | /// 88 | /// 双向链表元素类型 89 | /// 双向链表 90 | /// 要移除的节点 91 | public static void Remove(LinkedList list, LinkedListNode node) 92 | { 93 | list.Remove(node); 94 | } 95 | 96 | /// 97 | /// 从双向链表中移除指定值的第一个匹配项。 98 | /// 99 | /// 双向链表元素类型 100 | /// 双向链表 101 | /// 要移除的元素 102 | /// 如果成功移除了元素,则为 true;否则为 false。 103 | public static bool Remove(LinkedList list, T item) 104 | { 105 | return list.Remove(item); 106 | } 107 | 108 | /// 109 | /// 确定双向链表中是否包含特定值。 110 | /// 111 | /// 双向链表元素类型 112 | /// 双向链表 113 | /// 要在双向链表中查找的元素 114 | /// 如果在双向链表中找到了 item,则为 true;否则为 false。 115 | public static bool Contains(LinkedList list, T item) 116 | { 117 | return list.Contains(item); 118 | } 119 | 120 | /// 121 | /// 从双向链表中移除所有节点。 122 | /// 123 | /// 双向链表元素类型 124 | /// 双向链表 125 | public static void Clear(LinkedList list) 126 | { 127 | list.Clear(); 128 | } 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /EasyTool.Core/CollectionsCategory/ListExtension.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace EasyTool.Extension 7 | { 8 | public static class ListExtension 9 | { 10 | /// 11 | /// 判断两个列表是否相等。 12 | /// 13 | /// 列表元素类型 14 | /// 要比较的第一个列表 15 | /// 要比较的第二个列表 16 | /// 如果两个列表相等,则返回 true;否则返回 false 17 | public static bool Equals(this List list1, List list2)=> ListUtil.Equals(list1, list2); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /EasyTool.Core/CollectionsCategory/QueueExtension.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Collections.ObjectModel; 4 | using System.Linq; 5 | using System.Text; 6 | 7 | namespace EasyTool.Extension 8 | { 9 | /// 10 | /// 队列工具类 11 | /// 12 | public static class QueueExtension 13 | { 14 | 15 | /// 16 | /// 将指定集合中的元素添加到队列的末尾。 17 | /// 18 | /// 队列元素类型 19 | /// 队列 20 | /// 要添加到队列中的集合 21 | public static void EnqueueRange(this Queue queue, IEnumerable collection) => QueueUtil.EnqueueRange(queue, collection); 22 | 23 | /// 24 | /// 从队列中移除指定元素的第一个匹配项。 25 | /// 26 | /// 队列元素类型 27 | /// 队列 28 | /// 要移除的元素 29 | /// 如果已成功移除元素,则为 true;否则为 false。 30 | public static bool Remove(this Queue queue, T item) => QueueUtil.Remove(queue, item); 31 | 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /EasyTool.Core/CollectionsCategory/QueueUtil.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace EasyTool 7 | { 8 | /// 9 | /// 队列工具类 10 | /// 11 | public class QueueUtil 12 | { 13 | /// 14 | /// 将指定元素添加到队列的末尾。 15 | /// 16 | /// 队列元素类型 17 | /// 队列 18 | /// 要添加的元素 19 | public static void Enqueue(Queue queue, T item) 20 | { 21 | queue.Enqueue(item); 22 | } 23 | 24 | /// 25 | /// 将指定集合中的元素添加到队列的末尾。 26 | /// 27 | /// 队列元素类型 28 | /// 队列 29 | /// 要添加到队列中的集合 30 | public static void EnqueueRange(Queue queue, IEnumerable collection) 31 | { 32 | foreach (T item in collection) 33 | { 34 | queue.Enqueue(item); 35 | } 36 | } 37 | 38 | /// 39 | /// 移除并返回位于队列开头的元素。 40 | /// 41 | /// 队列元素类型 42 | /// 队列 43 | /// 队列开头的元素 44 | /// 队列为空时引发异常 45 | public static T Dequeue(Queue queue) 46 | { 47 | return queue.Dequeue(); 48 | } 49 | 50 | /// 51 | /// 返回位于队列开头的元素而不将其移除。 52 | /// 53 | /// 队列元素类型 54 | /// 队列 55 | /// 队列开头的元素 56 | /// 队列为空时引发异常 57 | public static T Peek(Queue queue) 58 | { 59 | return queue.Peek(); 60 | } 61 | 62 | /// 63 | /// 确定队列中是否包含指定元素。 64 | /// 65 | /// 队列元素类型 66 | /// 队列 67 | /// 要查找的元素 68 | /// 如果队列包含指定元素,则为 true;否则为 false。 69 | public static bool Contains(Queue queue, T item) 70 | { 71 | return queue.Contains(item); 72 | } 73 | 74 | /// 75 | /// 从队列中移除指定元素的第一个匹配项。 76 | /// 77 | /// 队列元素类型 78 | /// 队列 79 | /// 要移除的元素 80 | /// 如果已成功移除元素,则为 true;否则为 false。 81 | public static bool Remove(Queue queue, T item) 82 | { 83 | if (queue.Contains(item)) 84 | { 85 | queue = new Queue(queue.Where(x => !x.Equals(item))); 86 | return true; 87 | } 88 | return false; 89 | } 90 | 91 | /// 92 | /// 将队列中的所有元素复制到新数组中。 93 | /// 94 | /// 队列元素类型 95 | /// 队列 96 | /// 包含队列中所有元素的新数组 97 | public static T[] ToArray(Queue queue) 98 | { 99 | return queue.ToArray(); 100 | } 101 | 102 | /// 103 | /// 将队列中的所有元素复制到新数组中,从指定的索引开始。 104 | /// 105 | /// 队列元素类型 106 | /// 队列 107 | /// 要复制到的目标数组 108 | /// 目标数组的起始索引 109 | public static void CopyTo(Queue queue, T[] array, int arrayIndex) 110 | { 111 | queue.CopyTo(array, arrayIndex); 112 | } 113 | 114 | /// 115 | /// 从队列中移除所有元素。 116 | /// 117 | /// 队列元素类型 118 | /// 队列 119 | public static void Clear(Queue queue) 120 | { 121 | queue.Clear(); 122 | } 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /EasyTool.Core/CollectionsCategory/StackExtension.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace EasyTool.CollectionsCategory 7 | { 8 | public static class StackExtension 9 | { 10 | /// 11 | /// 从堆栈中移除指定元素的第一个匹配项。 12 | /// 13 | /// 堆栈元素类型 14 | /// 堆栈 15 | /// 要移除的元素 16 | /// 如果已成功移除元素,则为 true;否则为 false。 17 | public static bool Remove(this Stack stack, T item)=> StackUtil.Remove(stack, item); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /EasyTool.Core/CollectionsCategory/StackUtil.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace EasyTool 7 | { 8 | /// 9 | /// 堆栈工具类 10 | /// 11 | public class StackUtil 12 | { 13 | /// 14 | /// 将指定元素推入堆栈的顶部。 15 | /// 16 | /// 堆栈元素类型 17 | /// 堆栈 18 | /// 要添加的元素 19 | public static void Push(Stack stack, T item) 20 | { 21 | stack.Push(item); 22 | } 23 | 24 | /// 25 | /// 从堆栈的顶部移除并返回对象。 26 | /// 27 | /// 堆栈元素类型 28 | /// 堆栈 29 | /// 堆栈顶部的元素 30 | /// 堆栈为空时引发异常 31 | public static T Pop(Stack stack) 32 | { 33 | return stack.Pop(); 34 | } 35 | 36 | /// 37 | /// 返回位于堆栈顶部的对象但不将其移除。 38 | /// 39 | /// 堆栈元素类型 40 | /// 堆栈 41 | /// 堆栈顶部的元素 42 | /// 堆栈为空时引发异常 43 | public static T Peek(Stack stack) 44 | { 45 | return stack.Peek(); 46 | } 47 | 48 | /// 49 | /// 确定堆栈是否包含指定元素。 50 | /// 51 | /// 堆栈元素类型 52 | /// 堆栈 53 | /// 要查找的元素 54 | /// 如果堆栈包含指定元素,则为 true;否则为 false。 55 | public static bool Contains(Stack stack, T item) 56 | { 57 | return stack.Contains(item); 58 | } 59 | 60 | /// 61 | /// 从堆栈中移除指定元素的第一个匹配项。 62 | /// 63 | /// 堆栈元素类型 64 | /// 堆栈 65 | /// 要移除的元素 66 | /// 如果已成功移除元素,则为 true;否则为 false。 67 | public static bool Remove(Stack stack, T item) 68 | { 69 | if (stack.Contains(item)) 70 | { 71 | stack = new Stack(stack.Where(x => !x.Equals(item)).Reverse()); 72 | return true; 73 | } 74 | return false; 75 | } 76 | 77 | /// 78 | /// 将堆栈中的所有元素复制到新数组中。 79 | /// 80 | /// 堆栈元素类型 81 | /// 堆栈 82 | /// 包含堆栈中所有元素的新数组 83 | public static T[] ToArray(Stack stack) 84 | { 85 | return stack.ToArray(); 86 | } 87 | 88 | /// 89 | /// 将堆栈中的所有元素复制到新数组中,从指定的索引开始。 90 | /// 91 | /// 堆栈元素类型 92 | /// 堆栈 93 | /// 要复制到的目标数组 94 | /// 目标数组的起始索引 95 | public static void CopyTo(Stack stack, T[] array, int arrayIndex) 96 | { 97 | stack.CopyTo(array, arrayIndex); 98 | } 99 | 100 | /// 101 | /// 从堆栈中移除所有元素。 102 | /// 103 | /// 堆栈元素类型 104 | /// 堆栈 105 | public static void Clear(Stack stack) 106 | { 107 | stack.Clear(); 108 | } 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /EasyTool.Core/ConvertCategory/ConvertUtil.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace EasyTool 4 | { 5 | /// 6 | /// 类型转换工具类 7 | /// 8 | public static class ConvertUtil 9 | { 10 | /// 11 | /// 将对象转换为指定类型,转换失败返回指定类型的默认值 12 | /// 13 | public static T To(object value) 14 | { 15 | try 16 | { 17 | return (T)Convert.ChangeType(value, typeof(T)); 18 | } 19 | catch 20 | { 21 | return default(T); 22 | } 23 | } 24 | 25 | /// 26 | /// 将字符串转换为整型,转换失败返回0 27 | /// 28 | public static int ToInt32(string value) 29 | { 30 | int result; 31 | if (int.TryParse(value, out result)) 32 | { 33 | return result; 34 | } 35 | return 0; 36 | } 37 | 38 | /// 39 | /// 将字符串转换为长整型,转换失败返回0 40 | /// 41 | public static long ToInt64(string value) 42 | { 43 | long result; 44 | if (long.TryParse(value, out result)) 45 | { 46 | return result; 47 | } 48 | return 0; 49 | } 50 | 51 | /// 52 | /// 将字符串转换为布尔型,转换失败返回默认值,默认值false 53 | /// 54 | public static bool ToBoolean(string data, bool defValue = false) 55 | { 56 | //如果为空则返回默认值 57 | if (string.IsNullOrEmpty(data)) 58 | { 59 | return defValue; 60 | } 61 | 62 | bool temp = false; 63 | if (bool.TryParse(data, out temp)) 64 | { 65 | return temp; 66 | } 67 | else 68 | { 69 | return defValue; 70 | } 71 | } 72 | 73 | /// 74 | /// 将对象转换为布尔型,转换失败返回默认值,默认值false 75 | /// 76 | public static bool ToBoolean(object data, bool defValue = false) 77 | { 78 | //如果为空则返回默认值 79 | if (data == null || Convert.IsDBNull(data)) 80 | { 81 | return defValue; 82 | } 83 | 84 | try 85 | { 86 | return Convert.ToBoolean(data); 87 | } 88 | catch 89 | { 90 | return defValue; 91 | } 92 | } 93 | 94 | /// 95 | /// 将字符串转换为单精度浮点型,转换失败返回0 96 | /// 97 | public static float ToSingle(string value) 98 | { 99 | float result; 100 | if (float.TryParse(value, out result)) 101 | { 102 | return result; 103 | } 104 | return 0; 105 | } 106 | 107 | /// 108 | /// 将字符串转换为双精度浮点型,转换失败返回0 109 | /// 110 | public static double ToDouble(string value) 111 | { 112 | double result; 113 | if (double.TryParse(value, out result)) 114 | { 115 | return result; 116 | } 117 | return 0; 118 | } 119 | 120 | /// 121 | /// 将字符串转换为十进制数,转换失败返回0 122 | /// 123 | public static decimal ToDecimal(string value) 124 | { 125 | decimal result; 126 | if (decimal.TryParse(value, out result)) 127 | { 128 | return result; 129 | } 130 | return 0; 131 | } 132 | 133 | /// 134 | /// 将字符串转换为日期时间,转换失败返回DateTime.MinValue 135 | /// 136 | public static DateTime ToDateTime(string value) 137 | { 138 | DateTime result; 139 | if (DateTime.TryParse(value, out result)) 140 | { 141 | return result; 142 | } 143 | return DateTime.MinValue; 144 | } 145 | 146 | /// 147 | /// 将字符串转换为枚举类型,转换失败返回默认值 148 | /// 149 | public static T ToEnum(string value, T defaultValue = default(T)) where T : struct 150 | { 151 | T result; 152 | if (Enum.TryParse(value, out result)) 153 | { 154 | return result; 155 | } 156 | return defaultValue; 157 | } 158 | 159 | 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /EasyTool.Core/DateTimeCategory/DateTimeExtension.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Text; 5 | 6 | namespace EasyTool.Extension 7 | { 8 | /// 9 | /// 提供各种日期操作和计算的工具类。 10 | /// 11 | public static class DateTimeExtension 12 | { 13 | /// 14 | /// 获取指定日期所在周的第一天的日期。 15 | /// 16 | /// 指定日期。 17 | /// 指定日期所在周的第一天的日期。 18 | public static DateTime GetFirstDayOfWeek(this DateTime date) => DateTimeUtil.GetFirstDayOfWeek(date); 19 | 20 | /// 21 | /// 获取指定日期所在月份的第一天的日期。 22 | /// 23 | /// 指定日期。 24 | /// 指定日期所在月份的第一天的日期。 25 | public static DateTime GetFirstDayOfMonth(this DateTime date) => DateTimeUtil.GetFirstDayOfMonth(date); 26 | 27 | 28 | /// 29 | /// 获取指定日期所在季度的第一天的日期。 30 | /// 31 | /// 指定日期。 32 | /// 指定日期所在季度的第一天的日期。 33 | public static DateTime GetFirstDayOfQuarter(this DateTime date) => DateTimeUtil.GetFirstDayOfQuarter(date); 34 | 35 | /// 36 | /// 获取指定日期所在年份的第一天的日期。 37 | /// 38 | /// 指定日期。 39 | /// 指定日期所在年份的第一天的日期。 40 | public static DateTime GetFirstDayOfYear(this DateTime date) => DateTimeUtil.GetFirstDayOfYear(date); 41 | 42 | /// 43 | /// 计算指定日期和当前日期之间的天数差。 44 | /// 45 | /// 指定日期。 46 | /// 指定日期和当前日期之间的天数差。 47 | public static int GetDaysBetween(this DateTime date) => DateTimeUtil.GetDaysBetween(date); 48 | 49 | /// 50 | /// 计算两个日期之间的天数差。 51 | /// 52 | /// 第一个日期。 53 | /// 第二个日期。 54 | /// 两个日期之间的天数差。 55 | public static int GetDaysBetween(this DateTime date1, DateTime date2) => DateTimeUtil.GetDaysBetween(date1, date2); 56 | 57 | /// 58 | /// 计算指定日期和当前日期之间的工作日数差。 59 | /// 60 | /// 指定日期。 61 | /// 指定日期和当前日期之间的工作日数差。 62 | public static int GetWorkDaysBetween(this DateTime date) => DateTimeUtil.GetWorkDaysBetween(date); 63 | 64 | /// 65 | /// 计算两个日期之间的工作日数差。 66 | /// 67 | /// 第一个日期。 68 | /// 第二个日期。 69 | /// 两个日期之间的工作日数差。 70 | public static int GetWorkDaysBetween(this DateTime date1, DateTime date2) => DateTimeUtil.GetWorkDaysBetween(date1, date2); 71 | 72 | /// 73 | /// 判断指定日期是否是工作日。 74 | /// 75 | /// 指定日期。 76 | /// 如果是工作日,则返回 true;否则返回 false。 77 | public static bool IsWorkDay(this DateTime date) => DateTimeUtil.IsWorkDay(date); 78 | 79 | /// 80 | /// 获取指定日期所在周的所有日期。 81 | /// 82 | /// 指定日期。 83 | /// 指定日期所在周的所有日期。 84 | public static List GetWeekDays(this DateTime date) => DateTimeUtil.GetWeekDays(date); 85 | 86 | /// 87 | /// 获取指定日期所在月份的所有日期。 88 | /// 89 | /// 指定日期。 90 | /// 指定日期所在月份的所有日期。 91 | public static List GetMonthDays(this DateTime date) => DateTimeUtil.GetMonthDays(date); 92 | 93 | /// 94 | /// 获取指定日期所在季度的所有日期。 95 | /// 96 | /// 指定日期。 97 | /// 指定日期所在季度的所有日期。 98 | public static List GetQuarterDays(this DateTime date) => DateTimeUtil.GetQuarterDays(date); 99 | 100 | /// 101 | /// 获取指定日期所在年份的所有日期。 102 | /// 103 | /// 指定日期。 104 | /// 指定日期所在年份的所有日期。 105 | public static List GetYearDays(this DateTime date) => DateTimeUtil.GetYearDays(date); 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /EasyTool.Core/DateTimeCategory/TimerUtil.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | 4 | namespace EasyTool 5 | { 6 | /// 7 | /// 计时器工具类,提供各种计时和时间间隔计算的方法。 8 | /// 9 | public class TimerUtil 10 | { 11 | /// 12 | /// 记录程序启动时间。 13 | /// 14 | private static readonly DateTime _startTime = DateTime.Now; 15 | 16 | /// 17 | /// 获取当前时间戳,即 Unix 时间戳,精确到毫秒。 18 | /// 19 | /// 当前时间戳。 20 | public static long GetCurrentTimestamp() 21 | { 22 | return DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(); 23 | } 24 | 25 | /// 26 | /// 获取程序启动时间。 27 | /// 28 | /// 程序启动时间。 29 | public static DateTime GetStartTime() 30 | { 31 | return _startTime; 32 | } 33 | 34 | /// 35 | /// 获取当前时间距离程序启动时间的时间间隔。 36 | /// 37 | /// 当前时间距离程序启动时间的时间间隔。 38 | public static TimeSpan GetElapsedTime() 39 | { 40 | return DateTime.Now - _startTime; 41 | } 42 | 43 | /// 44 | /// 创建一个新的 Stopwatch 并启动计时。 45 | /// 46 | /// 一个新的 Stopwatch。 47 | public static Stopwatch StartNew() 48 | { 49 | Stopwatch stopwatch = new Stopwatch(); 50 | stopwatch.Start(); 51 | return stopwatch; 52 | } 53 | 54 | /// 55 | /// 计算指定操作的执行时间。 56 | /// 57 | /// 要执行的操作。 58 | /// 操作执行的时间。 59 | public static TimeSpan Measure(Action action) 60 | { 61 | Stopwatch stopwatch = new Stopwatch(); 62 | stopwatch.Start(); 63 | action.Invoke(); 64 | stopwatch.Stop(); 65 | return stopwatch.Elapsed; 66 | } 67 | 68 | /// 69 | /// 计算指定操作的执行时间,并输出执行结果。 70 | /// 71 | /// 要执行的操作。 72 | /// 执行结果的描述。 73 | public static void MeasureAndPrint(Action action, string description) 74 | { 75 | TimeSpan elapsedTime = Measure(action); 76 | Console.WriteLine($"{description}: {elapsedTime.TotalMilliseconds}ms"); 77 | } 78 | 79 | /// 80 | /// 计算指定操作的执行时间,并输出执行结果到指定文件。 81 | /// 82 | /// 要执行的操作。 83 | /// 输出结果的文件名。 84 | public static void MeasureAndSave(Action action, string fileName) 85 | { 86 | TimeSpan elapsedTime = Measure(action); 87 | System.IO.File.WriteAllText(fileName, elapsedTime.TotalMilliseconds.ToString()); 88 | } 89 | 90 | /// 91 | /// 计算指定操作的执行时间,并将执行结果添加到指定日志文件的末尾。 92 | /// 93 | /// 要执行的操作。 94 | /// 日志文件名。 95 | public static void MeasureAndLog(Action action, string fileName) 96 | { 97 | TimeSpan elapsedTime = Measure(action); 98 | System.IO.File.AppendAllText(fileName, $"{DateTime.Now}: {elapsedTime.TotalMilliseconds}ms{Environment.NewLine}"); 99 | } 100 | 101 | /// 102 | /// 等待指定的时间 103 | /// 104 | /// 要等待的毫秒数。 105 | public static void Wait(int milliseconds) 106 | { 107 | System.Threading.Thread.Sleep(milliseconds); 108 | } 109 | 110 | /// 111 | /// 计算两个时间的时间间隔。 112 | /// 113 | /// 第一个时间。 114 | /// 第二个时间。 115 | /// 两个时间的时间间隔。 116 | public static TimeSpan GetTimeSpan(DateTime time1, DateTime time2) 117 | { 118 | return time1 - time2; 119 | } 120 | 121 | /// 122 | /// 计算两个时间戳的时间间隔。 123 | /// 124 | /// 第一个时间戳。 125 | /// 第二个时间戳。 126 | /// 两个时间戳的时间间隔。 127 | public static TimeSpan GetTimeSpan(long timestamp1, long timestamp2) 128 | { 129 | DateTime time1 = DateTimeOffset.FromUnixTimeMilliseconds(timestamp1).LocalDateTime; 130 | DateTime time2 = DateTimeOffset.FromUnixTimeMilliseconds(timestamp2).LocalDateTime; 131 | return GetTimeSpan(time1, time2); 132 | } 133 | 134 | /// 135 | /// 将时间间隔格式化为友好的字符串,例如 1h 20m 30s。 136 | /// 137 | /// 要格式化的时间间隔。 138 | /// 格式化后的字符串。 139 | public static string FormatTimeSpan(TimeSpan timeSpan) 140 | { 141 | int hours = timeSpan.Days * 24 + timeSpan.Hours; 142 | string formattedTimeSpan = $"{hours}h {timeSpan.Minutes}m {timeSpan.Seconds}s"; 143 | return formattedTimeSpan; 144 | } 145 | 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /EasyTool.Core/DateTimeCategory/TimestampUtil.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace EasyTool 4 | { 5 | /// 6 | /// 时间戳处理工具类 7 | /// 8 | public static class TimestampUtil 9 | { 10 | /// 11 | /// 获取当前时间戳(毫秒级) 12 | /// 13 | /// 当前时间戳(毫秒级) 14 | public static long GetCurrentTimestamp() 15 | { 16 | DateTime dt = DateTime.UtcNow; 17 | TimeSpan ts = dt - new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); 18 | return (long)ts.TotalMilliseconds; 19 | } 20 | 21 | /// 22 | /// 将时间戳(毫秒级)转换为 DateTime 类型 23 | /// 24 | /// 时间戳(毫秒级) 25 | /// 转换后的 DateTime 类型 26 | public static DateTime ConvertToDateTime(long timestamp) 27 | { 28 | DateTime dt = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); 29 | return dt.AddMilliseconds(timestamp); 30 | } 31 | 32 | /// 33 | /// 将 DateTime 类型转换为时间戳(毫秒级) 34 | /// 35 | /// DateTime 类型 36 | /// 转换后的时间戳(毫秒级) 37 | public static long ConvertToTimestamp(DateTime dateTime) 38 | { 39 | TimeSpan ts = dateTime.ToUniversalTime() - new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); 40 | return (long)ts.TotalMilliseconds; 41 | } 42 | 43 | /// 44 | /// 获取当前时间戳(秒级) 45 | /// 46 | /// 当前时间戳(秒级) 47 | public static long GetCurrentTimestampSeconds() 48 | { 49 | return (long)(DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds; 50 | } 51 | 52 | /// 53 | /// 将时间戳(秒级)转换为 DateTime 类型 54 | /// 55 | /// 时间戳(秒级) 56 | /// 转换后的 DateTime 类型 57 | public static DateTime ConvertToDateTimeSeconds(long timestamp) 58 | { 59 | return new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc).AddSeconds(timestamp); 60 | } 61 | 62 | /// 63 | /// 将 DateTime 类型转换为时间戳(秒级) 64 | /// 65 | /// DateTime 类型 66 | /// 转换后的时间戳(秒级) 67 | public static long ConvertToTimestampSeconds(DateTime dateTime) 68 | { 69 | return (long)(dateTime.ToUniversalTime() - new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds; 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /EasyTool.Core/EasyTool.Core.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netstandard2.1;.net6.0 5 | 11 6 | enable 7 | $(MSBuildProjectName.Replace(" ", "_").Replace(".Core", "")) 8 | 9 | 一个大西瓜,TimChen 10 | 2023.0908.1 11 | 12 | A open source C# tool to make .NET easy 13 | 14 | Tool Power 15 | https://github.com/dotnet-easy/easytool 16 | https://easy-dotnet.com 17 | README.md 18 | LICENSE 19 | logo.png 20 | 21 | 22 | 23 | 24 | True 25 | \ 26 | 27 | 28 | True 29 | \ 30 | 31 | 32 | True 33 | \ 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | True 47 | \ 48 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /EasyTool.Core/EmojiCategory/EmojiUtil.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Text.RegularExpressions; 5 | 6 | namespace EasyTool 7 | { 8 | public class EmojiUtil 9 | { 10 | // Unicode 区间:Emoji 表情符号的 Unicode 区间 11 | private const string EmojiRanges = "[\u1F600-\u1F64F\u1F910-\u1F96B\u1F980-\u1F9E0]"; 12 | 13 | // 表情符号的正则表达式 14 | private static readonly Regex EmojiRegex = new Regex(EmojiRanges, RegexOptions.Compiled); 15 | 16 | /// 17 | /// 判断字符串中是否包含 Emoji 表情符号 18 | /// 19 | /// 要检查的字符串 20 | /// 如果包含 Emoji 表情符号则返回 true,否则返回 false 21 | public static bool ContainsEmoji(string text) 22 | { 23 | return EmojiRegex.IsMatch(text); 24 | } 25 | 26 | /// 27 | /// 删除字符串中的 Emoji 表情符号 28 | /// 29 | /// 要删除 Emoji 表情符号的字符串 30 | /// 删除 Emoji 表情符号后的字符串 31 | public static string RemoveEmoji(string text) 32 | { 33 | return EmojiRegex.Replace(text, ""); 34 | } 35 | 36 | 37 | /// 38 | /// 将字符串中的 Emoji 表情符号转换为对应的 Unicode 码点 39 | /// 40 | /// 要转换的字符串 41 | /// 转换后的字符串 42 | public static string ConvertEmojiToUnicode(string text) 43 | { 44 | return EmojiRegex.Replace(text, m => ((int)m.Value[0]).ToString("X").ToLower()); 45 | } 46 | 47 | /// 48 | /// 将字符串中的 Emoji 表情符号转换为对应的 HTML 实体编码 49 | /// 50 | /// 要转换的字符串 51 | /// 转换后的字符串 52 | public static string ConvertEmojiToHtmlEntities(string text) 53 | { 54 | var stringBuilder = new StringBuilder(); 55 | 56 | foreach (char c in text) 57 | { 58 | if (char.IsSurrogatePair(c, c)) 59 | { 60 | // 如果是代理项对,则将其转换为 Unicode 码点再转换为 HTML 实体编码 61 | var codepoint = char.ConvertToUtf32(c, text[text.IndexOf(c) + 1]); 62 | stringBuilder.Append("&#x").Append(codepoint.ToString("X")).Append(";"); 63 | } 64 | else if (EmojiRegex.IsMatch(c.ToString())) 65 | { 66 | // 如果是 Emoji 表情符号,则将其转换为对应的 HTML 实体编码 67 | stringBuilder.Append("&#x").Append(((int)c).ToString("X")).Append(";"); 68 | } 69 | else 70 | { 71 | // 否则直接追加到字符串中 72 | stringBuilder.Append(c); 73 | } 74 | } 75 | 76 | return stringBuilder.ToString(); 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /EasyTool.Core/IEnumerableCategory/IEnumerableExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace EasyTool.IEnumerableCategory 7 | { 8 | /// 9 | /// 通用拓展 10 | /// 11 | public static class IEnumerableExtensions 12 | { 13 | 14 | 15 | 16 | #region IEnumerable拓展 17 | /// 18 | /// 对List 等集合Foreach的时候不用在上层判空,直接加上这个就好 19 | /// 20 | /// 21 | /// 22 | /// 23 | public static IEnumerable CheckNull(this IEnumerable values) 24 | { 25 | return values is null ? new List(0) : values; 26 | } 27 | 28 | #region 集合运算 29 | /// 30 | /// 求集合的笛卡尔积 31 | /// 32 | public static IEnumerable> Cartesian(this IEnumerable> sequences) 33 | { 34 | IEnumerable> tempProduct = new[] { Enumerable.Empty() }; 35 | return sequences.Aggregate(tempProduct, 36 | (accumulator, sequence) => 37 | from accseq in accumulator 38 | from item in sequence 39 | select accseq.Concat(new[] { item 40 | })); 41 | } 42 | 43 | #endregion 44 | #endregion 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /EasyTool.Core/IOCategory/FileTypeExtension.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Text; 5 | 6 | namespace EasyTool.Extension 7 | { 8 | public static class FileTypeExtension 9 | { 10 | /// 11 | /// 文件流头部信息获得文件类型 12 | /// 13 | /// 说明: 14 | /// 1、无法识别类型默认按照扩展名识别 15 | /// 2、xls、doc、msi、ppt、vsd头信息无法区分,按照扩展名区分 16 | /// 3、zip可能为docx、xlsx、pptx、jar、war头信息无法区分,按照扩展名区分 17 | /// 18 | /// 文件 19 | /// 类型,文件的扩展名,未找到为null 20 | public static string GetType(this FileInfo file) => FileTypeUtil.GetType(file); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /EasyTool.Core/IOCategory/FileTypeUtil.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Text; 5 | 6 | namespace EasyTool 7 | { 8 | /// 9 | /// 文件类型判断工具类 10 | /// 11 | public class FileTypeUtil 12 | { 13 | /// 14 | /// 文件流头部信息获得文件类型 15 | /// 16 | /// 说明: 17 | /// 1、无法识别类型默认按照扩展名识别 18 | /// 2、xls、doc、msi、ppt、vsd头信息无法区分,按照扩展名区分 19 | /// 3、zip可能为docx、xlsx、pptx、jar、war头信息无法区分,按照扩展名区分 20 | /// 21 | /// 文件 22 | /// 类型,文件的扩展名,未找到为null 23 | public static string GetType(FileInfo file) 24 | { 25 | byte[] buffer = new byte[256]; 26 | using (FileStream fs = file.OpenRead()) 27 | { 28 | if (fs.Length >= 256) 29 | fs.Read(buffer, 0, 256); 30 | else 31 | fs.Read(buffer, 0, (int)fs.Length); 32 | } 33 | 34 | string header = ""; 35 | for (int i = 0; i < buffer.Length; i++) 36 | { 37 | header += buffer[i].ToString(); 38 | } 39 | 40 | string type = null; 41 | switch (header) 42 | { 43 | case "255216": // jpg 44 | type = ".jpg"; 45 | break; 46 | case "13780": // png 47 | type = ".png"; 48 | break; 49 | case "7173": // gif 50 | type = ".gif"; 51 | break; 52 | case "6677": // bmp 53 | type = ".bmp"; 54 | break; 55 | case "7790": // exe dll 56 | type = ".exe"; 57 | break; 58 | case "6063": // xml 59 | type = ".xml"; 60 | break; 61 | case "6033": // htm html 62 | type = ".html"; 63 | break; 64 | case "4742": // js 65 | type = ".js"; 66 | break; 67 | case "5144": // txt 68 | type = ".txt"; 69 | break; 70 | default: 71 | case "8297": // rar 72 | case "8075": // zip 73 | case "D0CF11E0": // doc xls ppt vsd 74 | type = file.Extension; 75 | break; 76 | } 77 | 78 | return type; 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /EasyTool.Core/IOCategory/IoUtil.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Net; 5 | using System.Text; 6 | 7 | namespace EasyTool 8 | { 9 | /// 10 | /// Io流处理工具类 11 | /// 12 | public static class IoUtil 13 | { 14 | /// 15 | /// 读取文件的所有行到一个字符串数组中 16 | /// 17 | /// 文件路径 18 | /// 字符串数组,其中包含文件的所有行。 19 | public static string[] ReadAllLines(string path) 20 | { 21 | return File.ReadAllLines(path); 22 | } 23 | 24 | /// 25 | /// 将字符串数组写入文件,覆盖原有内容 26 | /// 27 | /// 文件路径 28 | /// 待写入的字符串数组 29 | public static void WriteAllLines(string path, string[] lines) 30 | { 31 | File.WriteAllLines(path, lines); 32 | } 33 | 34 | /// 35 | /// 读取整个文件到一个字符串中 36 | /// 37 | /// 文件路径 38 | /// 文件的所有内容 39 | public static string ReadAllText(string path) 40 | { 41 | return File.ReadAllText(path); 42 | } 43 | 44 | /// 45 | /// 将字符串写入文件,覆盖原有内容 46 | /// 47 | /// 文件路径 48 | /// 待写入的字符串 49 | public static void WriteAllText(string path, string text) 50 | { 51 | File.WriteAllText(path, text); 52 | } 53 | 54 | /// 55 | /// 读取二进制数据到一个字节数组中 56 | /// 57 | /// 文件路径 58 | /// 59 | public static byte[] ReadAllBytes(string path) 60 | { 61 | return File.ReadAllBytes(path); 62 | } 63 | 64 | /// 65 | /// 将字节数组写入二进制文件,覆盖原有内容 66 | /// 67 | /// 文件路径 68 | /// 待写入的字节数组 69 | public static void WriteAllBytes(string path, byte[] bytes) 70 | { 71 | File.WriteAllBytes(path, bytes); 72 | } 73 | 74 | /// 75 | /// 读取指定 URL 的文本内容 76 | /// 77 | /// URL 地址 78 | /// URL 返回的文本内容 79 | public static string ReadUrl(string url) 80 | { 81 | WebClient client = new WebClient(); 82 | return client.DownloadString(url); 83 | } 84 | 85 | /// 86 | /// 将字符串写入指定 URL 87 | /// 88 | /// URL 地址 89 | /// 待写入的字符串 90 | public static void WriteUrl(string url, string text) 91 | { 92 | WebClient client = new WebClient(); 93 | client.UploadString(url, text); 94 | } 95 | 96 | /// 97 | /// 读取网络流到一个字符串中 98 | /// 99 | /// 网络流 100 | /// 网络流的所有内容 101 | public static string ReadStream(Stream stream) 102 | { 103 | using (StreamReader reader = new StreamReader(stream)) 104 | { 105 | return reader.ReadToEnd(); 106 | } 107 | } 108 | 109 | /// 110 | /// 将字符串写入网络流 111 | /// 112 | /// 网络流 113 | /// 待写入的字符串 114 | public static void WriteStream(Stream stream, string text) 115 | { 116 | using (StreamWriter writer = new StreamWriter(stream)) 117 | { 118 | writer.Write(text); 119 | } 120 | } 121 | 122 | /// 123 | /// 读取二进制数据到一个内存流中 124 | /// 125 | /// 二进制数据 126 | /// 内存流,其中包含输入的二进制数据 127 | public static MemoryStream ReadMemoryStream(byte[] bytes) 128 | { 129 | return new MemoryStream(bytes); 130 | } 131 | 132 | /// 133 | /// 将二进制数据写入一个内存流中 134 | /// 135 | /// 内存流 136 | /// 待写入的字节数组 137 | public static void WriteMemoryStream(MemoryStream stream, byte[] bytes) 138 | { 139 | stream.Write(bytes, 0, bytes.Length); 140 | } 141 | 142 | /// 143 | /// 将一个字符串转换为字节数组 144 | /// 145 | /// 待转换的字符串 146 | /// 字节数组,其中包含输入字符串的编码数据 147 | public static byte[] StringToBytes(string text) 148 | { 149 | return Encoding.UTF8.GetBytes(text); 150 | } 151 | 152 | /// 153 | /// 将一个字节数组转换为字符串 154 | /// 155 | /// 待转换的字节数组 156 | /// 字符串,其中包含输入字节数组的编码数据 157 | public static string BytesToString(byte[] bytes) 158 | { 159 | return Encoding.UTF8.GetString(bytes); 160 | } 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /EasyTool.Core/IOCategory/Tailer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Text; 5 | using System.Threading; 6 | 7 | namespace EasyTool 8 | { 9 | /// 10 | /// 文件跟随工具类 11 | /// 12 | public class Tailer : IDisposable 13 | { 14 | private readonly string filePath; // 被监视的文件路径 15 | private readonly StreamReader reader; // 用于读取文件内容的 StreamReader 16 | private readonly Timer timer; // 定时器,用于定期检查文件是否有新内容 17 | 18 | // 定义事件,用于通知外部监听器 19 | public event EventHandler NewLine; 20 | 21 | // 构造函数,初始化文件路径、StreamReader 和定时器 22 | public Tailer(string filePath) 23 | { 24 | if (string.IsNullOrEmpty(filePath)) 25 | throw new ArgumentNullException(nameof(filePath)); 26 | 27 | if (!File.Exists(filePath)) 28 | throw new ArgumentException($"The specified file '{filePath}' does not exist."); 29 | 30 | this.filePath = filePath; 31 | 32 | // 初始化 StreamReader,注意要使用 FileShare.ReadWrite 参数,以便其他进程可以同时访问文件 33 | reader = new StreamReader(new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)); 34 | 35 | // 初始化定时器,每隔 1 秒触发一次 OnTimerCallback 方法 36 | timer = new Timer(OnTimerCallback, null, TimeSpan.Zero, TimeSpan.FromSeconds(1)); 37 | } 38 | 39 | // 定时器回调方法,检查文件是否有新内容 40 | private void OnTimerCallback(object state) 41 | { 42 | // 如果 StreamReader 不可用,直接返回 43 | if (reader == null || reader.BaseStream == null || !reader.BaseStream.CanRead) 44 | return; 45 | 46 | // 如果已经读到文件末尾,直接返回 47 | if (reader.EndOfStream) 48 | return; 49 | 50 | // 逐行读取文件内容 51 | string line; 52 | while ((line = reader.ReadLine()) != null) 53 | { 54 | // 如果有新行,触发 NewLine 事件 55 | if (NewLine != null) 56 | { 57 | NewLine(this, line); 58 | } 59 | } 60 | } 61 | 62 | // IDisposable 接口实现方法,释放资源 63 | public void Dispose() 64 | { 65 | timer.Dispose(); 66 | reader.Dispose(); 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /EasyTool.Core/IOCategory/WatchMonitor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Text; 5 | 6 | namespace EasyTool 7 | { 8 | /// 9 | /// 文件监听工具类 10 | /// 11 | public class WatchMonitor 12 | { 13 | private readonly FileSystemWatcher watcher; 14 | 15 | // 定义事件,用于通知外部监听器 16 | public event EventHandler FileChanged; 17 | public event EventHandler FileCreated; 18 | public event EventHandler FileDeleted; 19 | public event EventHandler FileMissing; 20 | public event EventHandler FileError; 21 | 22 | /// 23 | /// 构造函数,初始化 FileSystemWatcher 实例 24 | /// 25 | /// 26 | /// 27 | /// 28 | public WatchMonitor(string path) 29 | { 30 | if (string.IsNullOrEmpty(path)) 31 | throw new ArgumentNullException(nameof(path)); 32 | 33 | if (!Directory.Exists(path)) 34 | throw new ArgumentException($"The specified directory '{path}' does not exist."); 35 | 36 | watcher = new FileSystemWatcher(path); 37 | watcher.EnableRaisingEvents = true; 38 | 39 | watcher.Changed += OnFileChanged; 40 | watcher.Created += OnFileCreated; 41 | watcher.Deleted += OnFileDeleted; 42 | watcher.Renamed += OnFileRenamed; 43 | watcher.Error += OnFileError; 44 | } 45 | 46 | /// 47 | /// 文件修改事件处理方法 48 | /// 49 | /// 50 | /// 51 | private void OnFileChanged(object sender, FileSystemEventArgs e) 52 | { 53 | if (FileChanged != null) 54 | { 55 | FileChanged(this, new FileEventArgs(e.FullPath)); 56 | } 57 | } 58 | 59 | /// 60 | /// 文件创建事件处理方法 61 | /// 62 | /// 63 | /// 64 | private void OnFileCreated(object sender, FileSystemEventArgs e) 65 | { 66 | if (FileCreated != null) 67 | { 68 | FileCreated(this, new FileEventArgs(e.FullPath)); 69 | } 70 | } 71 | 72 | /// 73 | /// 文件删除事件处理方法 74 | /// 75 | /// 76 | /// 77 | private void OnFileDeleted(object sender, FileSystemEventArgs e) 78 | { 79 | if (FileDeleted != null) 80 | { 81 | FileDeleted(this, new FileEventArgs(e.FullPath)); 82 | } 83 | } 84 | 85 | /// 86 | /// 文件重命名事件处理方法 87 | /// 88 | /// 89 | /// 90 | private void OnFileRenamed(object sender, RenamedEventArgs e) 91 | { 92 | if (FileMissing != null) 93 | { 94 | FileMissing(this, new FileEventArgs(e.OldFullPath)); 95 | } 96 | 97 | if (FileCreated != null) 98 | { 99 | FileCreated(this, new FileEventArgs(e.FullPath)); 100 | } 101 | } 102 | 103 | /// 104 | /// 文件错误事件处理方法 105 | /// 106 | /// 107 | /// 108 | private void OnFileError(object sender, ErrorEventArgs e) 109 | { 110 | if (FileError != null) 111 | { 112 | FileError(this, new FileEventArgs(e.GetException())); 113 | } 114 | } 115 | 116 | /// 117 | /// IDisposable 接口实现方法,释放资源 118 | /// 119 | public void Dispose() 120 | { 121 | watcher.Changed -= OnFileChanged; 122 | watcher.Created -= OnFileCreated; 123 | watcher.Deleted -= OnFileDeleted; 124 | watcher.Renamed -= OnFileRenamed; 125 | watcher.Error -= OnFileError; 126 | watcher.Dispose(); 127 | } 128 | } 129 | 130 | /// 131 | /// 文件事件参数类,用于传递文件路径信息 132 | /// 133 | public class FileEventArgs : EventArgs 134 | { 135 | public string FilePath { get; } 136 | public Exception Exception { get; } 137 | 138 | public FileEventArgs(string path) 139 | { 140 | FilePath = path; 141 | } 142 | 143 | public FileEventArgs(Exception exception) 144 | { 145 | Exception = exception; 146 | } 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /EasyTool.Core/LanguageCategory/BCDUtil.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace EasyTool 6 | { 7 | /// 8 | /// BCD工具 9 | /// 10 | public class BCDUtil 11 | { 12 | /// 13 | /// 将一个十进制数转换成对应的二进制码数组 14 | /// 15 | /// 需要转换的十进制数 16 | /// 二进制码数组 17 | public static int[] DecToBinaryArray(int dec) 18 | { 19 | if (dec < 0) 20 | { 21 | throw new ArgumentException("dec必须是非负整数。"); 22 | } 23 | 24 | if (dec == 0) 25 | { 26 | return new int[] { 0 }; 27 | } 28 | 29 | int[] binaryArray = new int[32]; 30 | int index = 0; 31 | 32 | while (dec > 0) 33 | { 34 | binaryArray[index++] = dec % 2; 35 | dec /= 2; 36 | } 37 | 38 | Array.Resize(ref binaryArray, index); 39 | Array.Reverse(binaryArray); 40 | 41 | return binaryArray; 42 | } 43 | 44 | /// 45 | /// 将一个二进制码数组转换成对应的十进制数 46 | /// 47 | /// 需要转换的二进制码数组 48 | /// 对应的十进制数 49 | public static int BinaryArrayToDec(int[] binaryArray) 50 | { 51 | if (binaryArray == null) 52 | { 53 | throw new ArgumentNullException("binaryArray不能为null。"); 54 | } 55 | 56 | int dec = 0; 57 | int power = 1; 58 | 59 | for (int i = binaryArray.Length - 1; i >= 0; i--) 60 | { 61 | dec += binaryArray[i] * power; 62 | power *= 2; 63 | } 64 | 65 | return dec; 66 | } 67 | 68 | /// 69 | /// 将一个十进制数转换成对应的BCD码数组 70 | /// 71 | /// 需要转换的十进制数 72 | /// BCD码数组 73 | public static int[] DecToBCDArray(int dec) 74 | { 75 | if (dec < 0) 76 | { 77 | throw new ArgumentException("dec必须是非负整数。"); 78 | } 79 | 80 | if (dec == 0) 81 | { 82 | return new int[] { 0 }; 83 | } 84 | 85 | int[] bcdArray = new int[10]; 86 | int index = 0; 87 | 88 | while (dec > 0) 89 | { 90 | int remainder = dec % 10; 91 | int[] binaryArray = DecToBinaryArray(remainder); 92 | int paddingCount = 4 - binaryArray.Length; 93 | 94 | for (int i = 0; i < paddingCount; i++) 95 | { 96 | bcdArray[index++] = 0; 97 | } 98 | 99 | for (int i = 0; i < binaryArray.Length; i++) 100 | { 101 | bcdArray[index++] = binaryArray[i]; 102 | } 103 | 104 | dec /= 10; 105 | } 106 | 107 | Array.Resize(ref bcdArray, index); 108 | Array.Reverse(bcdArray); 109 | 110 | return bcdArray; 111 | } 112 | 113 | /// 114 | /// 将一个BCD码数组转换成对应的十进制数 115 | /// 116 | /// 需要转换的BCD码数组 117 | /// 对应的十进制数 118 | public static int BCDArrayToDec(int[] bcdArray) 119 | { 120 | if (bcdArray == null) 121 | { 122 | throw new ArgumentNullException("bcdArray不能为null。"); 123 | } 124 | 125 | int dec = 0; 126 | int power = 1; 127 | 128 | for (int i = bcdArray.Length - 1; i >= 0; i -= 4) 129 | { 130 | int binary = 0; 131 | 132 | for (int j = 0; j < 4; j++) 133 | { 134 | int index = i - j; 135 | 136 | if (index < 0) 137 | { 138 | break; 139 | } 140 | 141 | binary += bcdArray[index] * (int)Math.Pow(2, 3 - j); 142 | } 143 | 144 | dec += binary * power; 145 | power *= 10; 146 | } 147 | 148 | return dec; 149 | } 150 | 151 | /// 152 | /// 将给定的十进制数转换为 BCD 码字符串。 153 | /// 154 | /// 要转换的十进制数 155 | /// 转换后的 BCD 码字符串 156 | public static string Encode(int dec) 157 | { 158 | if (dec == 0) 159 | { 160 | return "0"; 161 | } 162 | 163 | string str = dec.ToString(); 164 | int len = str.Length; 165 | char[] bcdChars = new char[len * 2]; 166 | for (int i = 0; i < len; i++) 167 | { 168 | int bcd = ((int)Char.GetNumericValue(str[i])) & 0x0F; 169 | bcdChars[i * 2] = (char)(bcd + ((bcd > 9) ? 0x37 : 0x30)); 170 | 171 | bcd = (((int)Char.GetNumericValue(str[i])) >> 4) & 0x0F; 172 | bcdChars[i * 2 + 1] = (char)(bcd + ((bcd > 9) ? 0x37 : 0x30)); 173 | } 174 | return new string(bcdChars); 175 | } 176 | 177 | /// 178 | /// 将给定的 BCD 码字符串转换为十进制数。 179 | /// 180 | /// 要转换的 BCD 码字符串 181 | /// 转换后的十进制数 182 | public static int Decode(string bcd) 183 | { 184 | if (string.IsNullOrEmpty(bcd)) 185 | { 186 | return 0; 187 | } 188 | 189 | int len = bcd.Length; 190 | int dec = 0; 191 | for (int i = 0; i < len; i += 2) 192 | { 193 | int a = ((int)bcd[i]) & 0x0F; 194 | int b = ((int)bcd[i + 1]) & 0x0F; 195 | dec = dec * 100 + a + b * 10; 196 | } 197 | return dec; 198 | } 199 | } 200 | } 201 | -------------------------------------------------------------------------------- /EasyTool.Core/LanguageCategory/SingletonUtil.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace EasyTool 6 | { 7 | /// 8 | /// 单例工具类 9 | /// 10 | public class SingletonUtil where T : class, new() 11 | { 12 | private static readonly Lazy lazyInstance = new Lazy(() => new T()); 13 | 14 | /// 15 | /// 返回单例对象的唯一实例(懒汉模式) 16 | /// 17 | public static T LazyInstance => lazyInstance.Value; 18 | 19 | 20 | private static T instance; 21 | private static readonly object lockObject = new object(); 22 | 23 | /// 24 | /// 返回单例对象的唯一实例(饿汉模式) 25 | /// 26 | [Obsolete] 27 | public static T Instance 28 | { 29 | get 30 | { 31 | if (instance == null) 32 | { 33 | lock (lockObject) 34 | { 35 | if (instance == null) 36 | { 37 | instance = new T(); 38 | } 39 | } 40 | } 41 | 42 | return instance; 43 | } 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /EasyTool.Core/MathCategory/PredictUtil.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace EasyTool 7 | { 8 | /// 9 | /// 预测数据类 10 | /// 11 | public class PredictUtil 12 | { 13 | /// 14 | /// 线性回归预测 15 | /// 16 | /// 输入数据 17 | /// 输出数据 18 | /// 预测结果 19 | public static double LinearRegressionPredict(double[] inputData, double[] outputData) 20 | { 21 | // 获取输入数据的数量 22 | int n = inputData.Length; 23 | 24 | // 计算平均数 25 | double inputMean = inputData.Sum() / n; 26 | double outputMean = outputData.Sum() / n; 27 | 28 | // 计算分子和分母 29 | double numerator = 0; 30 | double denominator = 0; 31 | for (int i = 0; i < n; i++) 32 | { 33 | numerator += (inputData[i] - inputMean) * (outputData[i] - outputMean); 34 | denominator += Math.Pow(inputData[i] - inputMean, 2); 35 | } 36 | 37 | // 计算斜率 38 | double slope = numerator / denominator; 39 | 40 | // 计算截距 41 | double intercept = outputMean - slope * inputMean; 42 | 43 | // 返回预测结果 44 | return slope * inputData.Last() + intercept; 45 | } 46 | 47 | /// 48 | /// 构建多项式矩阵 49 | /// 50 | /// 输入数据 51 | /// 多项式的次数 52 | /// 多项式矩阵 53 | private static double[][] BuildMatrix(double[] inputData, int degree) 54 | { 55 | int n = inputData.Length; 56 | double[][] matrix = new double[n][]; 57 | for (int i = 0; i < n; i++) 58 | { 59 | matrix[i] = new double[degree + 1]; 60 | for (int j = 0; j < degree + 1; j++) 61 | { 62 | matrix[i][j] = Math.Pow(inputData[i], j); 63 | } 64 | } 65 | 66 | return matrix; 67 | } 68 | 69 | /// 70 | /// k近邻预测 71 | /// 72 | /// 输入数据 73 | /// 输出数据 74 | /// 邻居数量 75 | /// 预测结果 76 | public static double KNNPredict(double[] inputData, double[] outputData, int k) 77 | { 78 | // 计算距离数组 79 | double[] distances = new double[inputData.Length]; 80 | for (int i = 0; i < inputData.Length; i++) 81 | { 82 | distances[i] = Math.Abs(inputData[i] - inputData.Last()); 83 | } 84 | 85 | // 排序距离数组 86 | int[] sortedIndexes = Enumerable.Range(0, distances.Length) 87 | .OrderBy(i => distances[i]) 88 | .ToArray(); 89 | 90 | // 计算预测结果 91 | double result = 0; 92 | for (int i = 0; i < k; i++) 93 | { 94 | result += outputData[sortedIndexes[i]]; 95 | } 96 | 97 | return result / k; 98 | } 99 | 100 | ///// 101 | ///// 多项式回归预测 102 | ///// 103 | ///// 输入数据 104 | ///// 输出数据 105 | ///// 多项式的次数 106 | ///// 预测结果 107 | //public static double PolynomialRegressionPredict(double[] inputData, double[] outputData, int degree) 108 | //{ 109 | // // 创建多项式矩阵 110 | // Matrix X = DenseMatrix.OfArray(BuildMatrix(inputData, degree)); 111 | // Matrix Y = DenseMatrix.OfColumnVectors(new[] 112 | // { 113 | // DenseVector.OfArray(outputData) 114 | // }); 115 | 116 | // // 计算系数 117 | // Matrix coefficients = (X.Transpose() * X).Inverse() * X.Transpose() * Y; 118 | 119 | // // 计算预测结果 120 | // double result = 0; 121 | // for (int i = 0; i < degree + 1; i++) 122 | // { 123 | // result += coefficients[i, 0] * Math.Pow(inputData.Last(), i); 124 | // } 125 | 126 | // return result; 127 | //} 128 | 129 | ///// 130 | ///// 决策树回归预测 131 | ///// 132 | ///// 输入数据 133 | ///// 输出数据 134 | ///// 预测结果 135 | //public static double DecisionTreeRegressionPredict(double[] inputData, double[] outputData) 136 | //{ 137 | // var tree = new DecisionTreeRegression(inputData, outputData); 138 | // return tree.Compute(inputData.Last()); 139 | //} 140 | 141 | ///// 142 | ///// 随机森林回归预测 143 | ///// 144 | ///// 输入数据 145 | ///// 输出数据 146 | ///// 决策树数量 147 | ///// 预测结果 148 | //public static double RandomForestRegressionPredict(double[] inputData, double[] outputData, int trees) 149 | //{ 150 | // var forest = new RandomForestRegression(inputData, outputData, trees); 151 | // return forest.Compute(inputData.Last()); 152 | //} 153 | 154 | ///// 155 | ///// 梯度提升树回归预测 156 | ///// 157 | ///// 输入数据 158 | ///// 输出数据 159 | ///// 预测结果 160 | //public static double GradientBoostingRegressionPredict(double[] inputData, double[] outputData) 161 | //{ 162 | // var boosting = new GradientBoostingRegression(inputData, outputData); 163 | // return boosting.Compute(inputData.Last()); 164 | //} 165 | } 166 | } 167 | -------------------------------------------------------------------------------- /EasyTool.Core/NetCategory/NetUtil.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Net.NetworkInformation; 4 | using System.Net.Sockets; 5 | using System.Net; 6 | using System.Text; 7 | 8 | namespace EasyTool 9 | { 10 | /// 11 | /// 网络工具 12 | /// 13 | public class NetUtil 14 | { 15 | // Ping a host and return true if the ping was successful 16 | // 对指定主机进行Ping测试,返回是否成功 17 | public static bool Ping(string host) 18 | { 19 | try 20 | { 21 | Ping pingSender = new Ping(); 22 | PingReply reply = pingSender.Send(host); 23 | 24 | if (reply.Status == IPStatus.Success) 25 | { 26 | return true; 27 | } 28 | else 29 | { 30 | return false; 31 | } 32 | } 33 | catch 34 | { 35 | return false; 36 | } 37 | } 38 | 39 | // Resolve the IP address of a host 40 | // 获取指定主机的IP地址 41 | public static IPAddress GetIpAddress(string host) 42 | { 43 | try 44 | { 45 | IPHostEntry hostEntry = Dns.GetHostEntry(host); 46 | 47 | foreach (IPAddress address in hostEntry.AddressList) 48 | { 49 | // 返回IPv4地址 50 | if (address.AddressFamily == AddressFamily.InterNetwork) 51 | { 52 | return address; 53 | } 54 | } 55 | 56 | return null; 57 | } 58 | catch 59 | { 60 | return null; 61 | } 62 | } 63 | 64 | // Check if a port is open on a given IP address 65 | // 检查给定IP地址上的端口是否开放 66 | public static bool IsPortOpen(string host, int port) 67 | { 68 | try 69 | { 70 | // 获取IP地址 71 | IPAddress ipAddress = GetIpAddress(host); 72 | 73 | if (ipAddress == null) 74 | { 75 | return false; 76 | } 77 | 78 | // 创建套接字,连接端口 79 | IPEndPoint endpoint = new IPEndPoint(ipAddress, port); 80 | using (Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)) 81 | { 82 | socket.Connect(endpoint); 83 | return true; 84 | } 85 | } 86 | catch 87 | { 88 | return false; 89 | } 90 | } 91 | 92 | // Send an HTTP GET request and return the response 93 | // 发送HTTP GET请求并返回响应 94 | [Obsolete("建议使用HttpClient替代此方法")] 95 | public static string HttpGet(string url) 96 | { 97 | try 98 | { 99 | WebClient client = new WebClient(); 100 | return client.DownloadString(url); 101 | } 102 | catch 103 | { 104 | return null; 105 | } 106 | } 107 | 108 | // Send an HTTP POST request and return the response 109 | // 发送HTTP POST请求并返回响应 110 | [Obsolete("建议使用HttpClient替代此方法")] 111 | public static string HttpPost(string url, string data) 112 | { 113 | try 114 | { 115 | WebClient client = new WebClient(); 116 | // 设置请求头的内容类型 117 | client.Headers[HttpRequestHeader.ContentType] = "application/x-www-form-urlencoded"; 118 | return client.UploadString(url, data); 119 | } 120 | catch 121 | { 122 | return null; 123 | } 124 | } 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /EasyTool.Core/Standardization/Option.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Diagnostics; 5 | using System.Linq; 6 | using System.Reflection; 7 | 8 | 9 | namespace EasyTool 10 | { 11 | 12 | #if NET6_0_OR_GREATER 13 | /* 14 | *标准化与前端下拉选项数据结构,减少前后端对接工作 15 | */ 16 | 17 | /// 18 | /// 包含Value和Text的选择对象,用于前端下拉选项 19 | /// 20 | public record Option(T Value, string Text); 21 | 22 | /// 23 | /// 包含Value和Text的选择对象,用于前端下拉选项 24 | /// 25 | public record Option(string Value, string Text) : Option(Value, Text); 26 | 27 | /// 28 | /// 包含Value和Text的选择对象,用于前端下拉选项 29 | /// 30 | public record OptionInt(int? Value, string Text) : Option(Value, Text); 31 | 32 | /// 33 | /// 选项接口,用于描述选项的类 34 | /// 35 | /// 示例 36 | /// public class LogLevel 37 | /// { 38 | /// [DisplayName("调试")] 39 | /// public static string Debugg { get; set; } = nameof(Debugg); 40 | /// [DisplayName("消息")] 41 | /// public static string Info { get; set; } = nameof(Info); 42 | /// [DisplayName("警告")] 43 | /// public static string Warning { get; set; } = nameof(Warning); 44 | /// [DisplayName("错误")] 45 | /// public static string Error { get; set; } = nameof(Error); 46 | /// } 47 | /// DisplayName:用于前端显示 48 | /// 字段名称:用于代码编写 49 | /// 字段值:用于数据存储 50 | /// 51 | public interface IOption 52 | { 53 | /// 54 | /// 获得选项列表 55 | /// 56 | public static List