Yoko.Tool
3.0.0-beta.1
dotnet add package Yoko.Tool --version 3.0.0-beta.1
NuGet\Install-Package Yoko.Tool -Version 3.0.0-beta.1
<PackageReference Include="Yoko.Tool" Version="3.0.0-beta.1" />
paket add Yoko.Tool --version 3.0.0-beta.1
#r "nuget: Yoko.Tool, 3.0.0-beta.1"
// Install Yoko.Tool as a Cake Addin #addin nuget:?package=Yoko.Tool&version=3.0.0-beta.1&prerelease // Install Yoko.Tool as a Cake Tool #tool nuget:?package=Yoko.Tool&version=3.0.0-beta.1&prerelease
[TOC]
# Yoko.Tool
懒人必备工具箱
推荐使用 Yoko.Tool.Core
🍀功能示例
💎 值类型转换
// 值类型转换
.ToInt32()
.ToBool()
.ToLong()
.ToDouble()
.ToDecimal()
.ToFloat()
// 时间操作
.ToDateTime() // 字符串 转 时间
.ToStartTime() // DateTime转换成开始时间00:00:00
.ToEndTime() // DateTime转换成结束时间23:59:59
.ToUnixTime() // DateTime时间转Unix时间戳(默认精确到毫秒13位)
.ToUnixTimeS() // DateTime时间转Unix时间戳(默认精确到秒10位)
.ToLocalTime() // Unix时间戳转DateTime本地时间(yyyy/MM/dd hh:MM:ss)
.DateDiff() // 返回时间差(N小时前,N分钟前···)
.GetDiffTime() // 计算2个时间差(相差多少年月日时分秒)
.GetDaysOfMonth() // 本月有多少天
.GetWeekNameOfDay() // 返回当前日期的星期名称
DateTime.Now.GetDateTime(); //返回标准时间格式(yyyy-MM-dd HH:mm:ss)
DateTime.Now.GetDateTimeF(); //返回标准时间格式(yyyy-MM-dd HH:mm:ss:fffffff)
DateTime.Now.GetTotalSeconds(); // 获取该时间相对于1970-01-01 00:00:00的秒数
DateTime.Now.GetTotalMilliseconds(); // 获取该时间相对于1970-01-01 00:00:00的毫秒数
DateTime.Now.GetTotalMicroseconds(); // 获取该时间相对于1970-01-01 00:00:00的微秒数
//字符串操作
.SplitCsv() // 分割逗号的字符串为List[]、string[]
.SplitCsvToInt() // 分割逗号的字符串为int[]
.SplitCsvToLong() //将包含指定分隔符的字符串转换为 long 类型的数组
.ToIntList() // string数组转int数组
.ToFilterStr() // 过滤特殊字符[]^-_*×――(^)|'$%~!@#$…&%¥—+=<>《》!!???::•`·、。,;,.;\"‘’“”-
.ToByteArray() // string转换成字节数组
.ToJson() // 将一个对象转为Json格式字符串
.ToModel() // 反序列化一个JSON格式字符串为对象
.ToDynamic() // 将Json转为一个动态类型(运行时解析)
.ToMask() // 字符串敏感信息掩码 (123***789)
.ToMaskEmail() // 邮箱敏感信息掩码 (123****@163.com)
//值计算
//除法计算 a/b
//type=1 浮点数,保留2位小数(四舍五入):12.34
//type=2 百分比:12.23%
//type=3 带有逗号分隔符,保留小数位数(四舍五入):2,500,000.00
//type=4 货币表示,保留2位小数(四舍五入):¥12.34
DividedBy()
//DataTable 操作
DataTableHelper<T>.ToList(dt);
DataTableHelper<T>.ToModel(dt);
💎 值判断
// 在范围?
/**
int num = 50;
if (num.IsInRange(100, 1000)) { }
string value = "a";
if (value.IsIn("a", "b", "c")) { }
*/
IsInRange()
IsInRange()
IsIn()
IsContainsIn()
IsNullOrEmpty() // 是null或"" ?
IsValuable() // 有值?(与IsNullOrEmpty相反)
IsZero() // 是零?
IsInt() // 是Int?
IsNoInt() // 不是Int?
IsMoney() // 是金钱?
IsDate() // 是时间?
IsDate() // 是邮箱?
IsMobile() // 是手机号?(弱验证)
IsPhoneNumber() // 是手机号?(强验证)
IsTelephone() // 是座机?
IsIDcard() // 是身份证?
IsFax() // 是传真?
IsMatch() // 是适合正则匹配?
IsTrue() // 是true?
IsFalse() // 是false?
💎 随机数
Random rand = new Random();
// 生成一个真正的随机数
int randomNum = rand.StrictNext(0, 100);
Console.WriteLine($"真正的随机数: {randomNum}");
// 生成一个正态分布的随机数
double gaussNum = rand.NextGauss(0, 1);
Console.WriteLine($"正态分布的随机数: {gaussNum}");
// 根据规则生成随机字符串
// "?"代表一个字符,"#"代表一个一位数字,"*"代表一个字符串或一个一位数字
string patternString = rand.GetRandStringByPattern("???###***");
Console.WriteLine($"根据规则生成的随机字符串: {patternString}");
// 生成一个随机数值
int formatedNumeric = rand.GetFormatedNumeric(0, 100);
Console.WriteLine($"随机数值: {formatedNumeric}");
// 生成一个指定长度和字符的随机字符串
string randomString = rand.GetRandomString("abcdefghijklmnoaspqrstuvwxyzABCDEFGHIJKLMNasdfOPQRSTUVWXYZ0123456789", 10);
Console.WriteLine($"指定长度和字符的随机字符串: {randomString}");
// 生成一个指定长度的随机字符串
string randomString2 = rand.GetRandomString(10);
Console.WriteLine($"指定长度的随机字符串: {randomString2}");
// 生成一个指定长度的纯字母随机字符串
string randWord = rand.GetRandWord(7);
Console.WriteLine($"指定长度的纯字母随机字符串: {randWord}");
// 生成一个指定长度的纯数字随机数字串
string randomNumString = rand.GetRandomNum(5);
Console.WriteLine($"指定长度的纯数字随机数字串: {randomNumString}");
// 生成一个按照年月时分秒随机数生成的文件名
string randomFileName = rand.GetFileRndName();
Console.WriteLine($"按照年月时分秒随机数生成的文件名: {randomFileName}");
💎 集合/字典操作
🔍 对集合进行分组
/// 对集合进行分组
/// 指定要拆分成几个集合,集合中子集个数动态分配。
/// 如果原集合中子集的个数小于等于要分组数,既source.Count 小于等于 size,建议使用source.Chunk(1).ToList()
// 创建一个列表
List<int> numbers = Enumerable.Range(1, 10).ToList();
// 使用ChunkList方法将列表分成3个组
List<int[]> chunks = numbers.ChunkList(3);
// 打印每个组的内容
for (int i = 0; i < chunks.Count; i++)
{
Console.WriteLine($"Group {i + 1}: {string.Join(", ", chunks[i])}");
}
🔍 对参数进行排序
//==============对参数进行排序,并返回格式化的字符串。======================
// 创建一个字典
Dictionary<string, string> parameters = new Dictionary<string, string>
{
{ "param1", "value1" },
{ "param2", "value2" },
{ "param3", "value3" }
};
// 使用OrderByASCII方法对字典进行排序并返回格式化的字符串
string orderedParameters = parameters.OrderByASCII(); //参数区分大小写
//string orderedParameters = parameters.OrderByASCII(false); //不区分大小写
// 打印排序后的参数
Console.WriteLine($"Ordered parameters: {orderedParameters}");
💎 字符串相似度
🔍 Jaccard相似度
这种方法主要是通过计算两个集合交集的大小与并集的大小的比例来得到相似度
🔍 Sorensen Dice相似度系数
与Jaccard相似度类似,但计算方式略有不同,它是通过计算两个集合交集的2倍除以两个集合的和来得到相似度
🔍 汉明距离
明距离是编辑距离中的一个特殊情况,仅用来计算两个等长字符串中不一致的字符个数
var distance = "我爱编程".HammingDistance("我喜欢编程");
var distance = new SimHash("我爱编程").HammingDistance(new SimHash("我喜欢编程"));
// 创建两个字符串
string str1 = "我爱编程";
string str2 = "我喜欢编程";
// 创建两个SimHash对象
SimHash simHash1 = new SimHash(str1);
SimHash simHash2 = new SimHash(str2);
// 计算两个字符串的汉明距离
int distance = simHash1.HammingDistance(simHash2);
// 打印汉明距离
Console.WriteLine($"The Hamming distance between \"{str1}\" and \"{str2}\" is {distance}.");
var target = "12345678";
var targetSimHash = new SimHash(target);
var list = new List<string>(); // list 为一个 List<string> 的集合
var similarPlates = new List<string>();
foreach (var plate in list)
{
var plateSimHash = new SimHash(plate);
var similarity = targetSimHash.Similarity(plateSimHash);
if (similarity >= 0.9) // 设置阈值为0.9,即相似度为90%
{
similarPlates.Add(plate);
}
}
💎 一般密码加解密/验证
// MD5 加密、加盐
"123456".ToMD5()
"123456".ToMD5("abc123")
// 两次加密、加盐
"123456".ToMD5Double()
"123456".ToMD5Double("abc123")
// AES加密、解密(密钥)
"123456".ToAES()
"123456".ToAESDecrypt()
// DES加密、解密(密钥)
"123456".ToDES()
"123456".ToDESDecrypt()
// RSA加密、解密
RsaKey rsaKey = RsaCrypt.GenerateRsaKeys(); //生成RSA密钥对
string encrypt = "123456".RSAEncrypt(rsaKey.PublicKey); //公钥加密
string s = encrypt.RSADecrypt(rsaKey.PrivateKey);//私钥解密
// 用于生成一般账号的加密密码
// 默认MD5+哈希。生成密码组成: 标识头 + 迭代 + 哈希大小 + salt值 + 哈希值
// 设置标识头Key:YokoPassWord.Key = "yoko";
// 值表现为 : yoko:64000:18:salt值:哈希值
"123456".ToPassWord("要MD5加密?")
// 验证密码
"目标比对密码".IsTrue("输入的密码")
💎 国密
目前有的算法:AES,DES,RC4,TripleDES,RSA,SM2,SM3,SM4
支持 RSA XML 结构的 SecurityKey 和 Base64 格式的互转
本库不是去实现加密算法,而是基于.Net 提供的接口封装,为了方便使用
若是遇到了解密乱码,可能是需要引入一个包
在主项目中添加 System.Text.Encoding.CodePages 库,并在程序入口
Programe.cs
添加注册代码
var builder = WebApplication.CreateBuilder(args);
System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);
🔍 RC4
/// <summary>
/// RC4
/// </summary>
public void Rc4()
{
const string data = "Microsoft";
var key = "123456"u8.ToArray();
var byte_data = Encoding.UTF8.GetBytes(data);
var secret = Rc4Crypt.Encrypt(byte_data, key);
var base64 = secret.ToBase64();
// TZEdFUtAevoL
var data_result = Rc4Crypt.Decrypt(secret, key);
var result = Encoding.UTF8.GetString(data_result);
// result == data
}
🔍 RSA
private const string PublicKey =
"<RSAKeyValue><Modulus>p0H+4fFMZFIQq6LAhXNf3Zml3imiOCU6mzMiMcqRu/x5x08X3pWF6m+v+1T7fOo4P/2GYluZiuQzKveJnRLxV0O6kRdVivApZ6C/Lb8vnsnocaSlmEOoswdOZvmhe3s4tAQ4KlZerWdRYx3dUgoH862IUv6FNiSyF/z3TP4M50E=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>";
private const string PrivateKey =
"<RSAKeyValue><Modulus>p0H+4fFMZFIQq6LAhXNf3Zml3imiOCU6mzMiMcqRu/x5x08X3pWF6m+v+1T7fOo4P/2GYluZiuQzKveJnRLxV0O6kRdVivApZ6C/Lb8vnsnocaSlmEOoswdOZvmhe3s4tAQ4KlZerWdRYx3dUgoH862IUv6FNiSyF/z3TP4M50E=</Modulus><Exponent>AQAB</Exponent><P>2Nhp0/mM3qRkTqzUe5DeI5r5hmDS24XYsSteHKLNuD66sa0K1EFprTstw96+ZJdXW/bJ+R58j78YP1frkLFVpw==</P><Q>xXVq4nyP7UppDXXyKTjWindWmMTuD0v9el6EnyWiqaoaGRF6IAL1nKOcrh5O/BiFgBZm5cTn0knUNE8BzaFI1w==</Q><DP>T4ur3qe3pmC1ryq1U5LD+lm6WTIhh4flArD++BA82O6h+9WXmF9ajcKcujJ2s13VHRY95xXo6a5XDb2J221CFw==</DP><DQ>JpxaJSV0Q1MsjZxFmPfrQ7IoNcE0R7t1OktnJXOHhiOj7Mj1F3NcsZ9wkL+OdE8bM7utrTo+lmknXH8ifCIQiw==</DQ><InverseQ>VvMW94/iyBgKNH8N1Xdikn17BLC0a8tYsm/H/VDMXjaVngAXGqeN370Hd1Zukj0EGVw/vEl2YsAoJ6o9KmQgNA==</InverseQ><D>CkO8lrUuUQHQUBg+5HG+MmVZjpbTg8qVHC05LgEWjIjkGF08Q8a9XzPXgv8mJ/Zf2V1/v82LUMDMexiR83fUI8NxNuZjD+ldR1ZqmtE96+4laA0/WUH0fb1nBA6foVS+WB643nN01dJs0/3IV65k35GfkuqKDct6gld8/UFaN1k=</D></RSAKeyValue>";
private static readonly RsaSecretKey key = new(PrivateKey, PublicKey);
/// <summary>
/// 转换Key,Base64和XML格式互转. Java和其他语言里一般使用base64格式,.Net中一般为XML格式
/// </summary>
public void XmlToBase64Key()
{
// 私钥转换为Base64格式
var pri = RsaKeyConverter.ToBase64PrivateKey(PrivateKey);
// MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAKdB/uHxTGRSEKuiwIVzX92Zpd4pojglOpszIjHKkbv8ecdPF96Vhepvr/tU+3zqOD/9hmJbmYrkMyr3iZ0S8VdDupEXVYrwKWegvy2/L57J6HGkpZhDqLMHTmb5oXt7OLQEOCpWXq1nUWMd3VIKB/OtiFL+hTYkshf890z+DOdBAgMBAAECgYAKQ7yWtS5RAdBQGD7kcb4yZVmOltODypUcLTkuARaMiOQYXTxDxr1fM9eC/yYn9l/ZXX+/zYtQwMx7GJHzd9Qjw3E25mMP6V1HVmqa0T3r7iVoDT9ZQfR9vWcEDp+hVL5YHrjec3TV0mzT/chXrmTfkZ+S6ooNy3qCV3z9QVo3WQJBANjYadP5jN6kZE6s1HuQ3iOa+YZg0tuF2LErXhyizbg+urGtCtRBaa07LcPevmSXV1v2yfkefI+/GD9X65CxVacCQQDFdWrifI/tSmkNdfIpONaKd1aYxO4PS/16XoSfJaKpqhoZEXogAvWco5yuHk78GIWAFmblxOfSSdQ0TwHNoUjXAkBPi6vep7emYLWvKrVTksP6WbpZMiGHh+UCsP74EDzY7qH71ZeYX1qNwpy6MnazXdUdFj3nFejprlcNvYnbbUIXAkAmnFolJXRDUyyNnEWY9+tDsig1wTRHu3U6S2clc4eGI6PsyPUXc1yxn3CQv450Txszu62tOj6WaSdcfyJ8IhCLAkBW8xb3j+LIGAo0fw3Vd2KSfXsEsLRry1iyb8f9UMxeNpWeABcap43fvQd3Vm6SPQQZXD+8SXZiwCgnqj0qZCA0
// 公钥转换为Base64格式
var pub = RsaKeyConverter.ToBase64PublicKey(PublicKey);
// MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCnQf7h8UxkUhCrosCFc1/dmaXeKaI4JTqbMyIxypG7/HnHTxfelYXqb6/7VPt86jg//YZiW5mK5DMq94mdEvFXQ7qRF1WK8ClnoL8tvy+eyehxpKWYQ6izB05m+aF7ezi0BDgqVl6tZ1FjHd1SCgfzrYhS/oU2JLIX/PdM/gznQQIDAQAB
// 一样可以将Base64格式转换为XML格式
var xml_pri = RsaKeyConverter.ToXmlPrivateKey(pri);
// xml_pri == PrivateKey
var xml_pub = RsaKeyConverter.ToXmlPublicKey(pub);
// xml_pub == PublicKey
}
/// <summary>
/// RSA加密解密测试
/// </summary>
public void RsaEncryptAndDecrypt()
{
const string data = "Microsoft";
// 将原文解析到二进制数组格式
var byte_data = Encoding.UTF8.GetBytes(data);
RsaCrypt.Encrypt(key.PublicKey, byte_data, out var secret_data);
var secret_str = secret_data.ToBase64();
Console.WriteLine(secret_str);
RsaCrypt.Decrypt(key.PrivateKey, secret_str.FromBase64(), out var data_byte);
var result = Encoding.UTF8.GetString(data_byte);
// result == data
}
🔍 SM3
private const string data = "Microsoft";
/// <summary>
/// SM3测试16进制字符串格式
/// </summary>
public void SM3HexString()
{
var byte_data = Sm3Crypt.Crypt(data);
var hex = byte_data.ToHex();
hex.ToUpper().Should().Be("1749CE3E4EF7622F1EBABB52078EC86309CABD5A6073C8A0711BF35E19BA51B8");
}
/// <summary>
/// SM3测试Base64字符串格式
/// </summary>
public void SM3Base64()
{
var byte_data = Sm3Crypt.Crypt(data);
var base64 = byte_data.ToBase64();
base64.ToUpper().Should().Be("F0NOPK73YI8EURTSB47IYWNKVVPGC8IGCRVZXHM6UBG=");
}
🔍 SM4
/// <summary>
/// SM4ECB模式加密到Base64格式
/// </summary>
public void Sm4EncryptECBToBase64()
{
const string data = "Microsoft";
// 将原文解析到二进制数组格式
var byte_data = Encoding.UTF8.GetBytes(data);
// 进制格式密钥加密数据
var result = Sm4Crypt.EncryptECB("701d1cc0cfbe7ee11824df718855c0c6", true, byte_data);
// 获取Base64格式的字符串结果
var base64 = result.ToBase64();
// ThRruxZZm1GrHE5KkP4UmQ==
}
/// <summary>
/// SM4ECB模式解密Base64格式到字符串
/// </summary>
public void Sm4DecryptECBTest()
{
// Base64格式的
const string data = "ThRruxZZm1GrHE5KkP4UmQ==";
// 将Base64格式字符串转为 byte[]
var byte_data = Convert.FromBase64String(data);
// 通过16进制格式密钥解密数据
var result = Sm4Crypt.DecryptECB("701d1cc0cfbe7ee11824df718855c0c6", true, byte_data);
// 解析结果获取字符串
var str = Encoding.UTF8.GetString(result);
// Microsoft
}
/// <summary>
/// SM4ECB模式加密到16进制字符串
/// </summary>
public void Sm4EncryptECBToHex16()
{
const string data = "Microsoft";
// 将原文解析到二进制数组格式
var byte_data = Encoding.UTF8.GetBytes(data);
// 使用16位长度的密钥加密
var result = Sm4Crypt.EncryptECB("1cc0cfbe7ee11824", false, byte_data);
// 将结果转为16进制字符串
var hex = result.ToHexString();
// D265DF0510C05FE836D3113B3ACEC714
}
/// <summary>
/// SM4ECB模式解密16进制字符串格式密文
/// </summary>
public void Sm4DecryptECBTest2()
{
const string data = "D265DF0510C05FE836D3113B3ACEC714";
var byte_data = data.FromHex();
var result = Sm4Crypt.DecryptECB("1cc0cfbe7ee11824", false, byte_data);
// 解析结果获取字符串
var str = Encoding.UTF8.GetString(result);
// Microsoft
}
/// <summary>
/// SM4CBC模式加密到Base64格式
/// </summary>
public void Sm4EncryptCBCTest()
{
const string data = "Microsoft";
var byte_data = Encoding.UTF8.GetBytes(data);
var result = Sm4Crypt.EncryptCBC("701d1cc0cfbe7ee11824df718855c0c6", true, "701d1cc0cfbe7ee11824df718855c0c5", byte_data);
var base64 = result.ToBase64();
// Q2iUaMuSHjLvq6GhUQnGTg==
}
/// <summary>
/// SM4CBC模式从Base64解密
/// </summary>
public void Sm4DecryptCBCTest()
{
const string data = "Q2iUaMuSHjLvq6GhUQnGTg==";
var byte_data = Convert.FromBase64String(data);
var result = Sm4Crypt.DecryptCBC("701d1cc0cfbe7ee11824df718855c0c6", true, "701d1cc0cfbe7ee11824df718855c0c5", byte_data);
var str = Encoding.UTF8.GetString(result);
// Microsoft
}
/// <summary>
/// SM4CBC模式加密到16进制字符串
/// </summary>
public void Sm4EncryptCBCTest2()
{
const string data = "Microsoft";
var byte_data = Encoding.UTF8.GetBytes(data);
var result = Sm4Crypt.EncryptCBC("1cc0cfbe7ee11824", false, "1cc0cfbe7ee12824", byte_data);
var hex = result.ToHexString();
// 1BD7A32E49B60B17698AAC9D1E4FEE4A
}
/// <summary>
/// SM4CBC模式从Hex16解密到字符串
/// </summary>
public void Sm4DecryptCBCTest2()
{
const string data = "1BD7A32E49B60B17698AAC9D1E4FEE4A";
var byte_data = data.FromHex();
var result = Sm4Crypt.DecryptCBC("1cc0cfbe7ee11824", false, "1cc0cfbe7ee12824", byte_data);
var str = Encoding.UTF8.GetString(result);
// Microsoft
}
💎 经纬度操作
//根据经纬度计算两点间距离
YokoLngLat.GetDistance(x1,y1,x2,y2)
//求一个包含经纬度集合的距离和
YokoLngLat.GetDistanceSum(dict);
//坐标系互转
YokoLngLat.GPSToAMap() // GPS转高德(WGS84 --> GCJ-02)
YokoLngLat.AMapToGPS() // 高德转GPS(GCJ-02 --> WGS84)
YokoLngLat.AMapToBMap() // 高德转百度(GCJ-02 --> BD-09)
YokoLngLat.BMapToAMap() // 百度转高德(BD-09 --> GCJ-02)
💎 URL 操作
🔍 分解URL信息
string url = "https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png?authorization=bce-auth-v1%2Fe8a94e73dad54d3a9";
// 分解URL信息 UrlSplit()
var data = url.UrlSplit();
// 协议
data.Scheme;
// 服务器地址
data.Host;
// 端口号
data.Port;
// 绝对路径
data.AbsolutePath;
// 本地路径
data.LocalPath;
// 路径的结构数组
data.Segments;
// 查询信息部分
data.Query;
// 问号(?) 分割后的部分
data.PathAndQuery;
json解读:
{
"Scheme": "https",
"Host": "www.baidu.com",
"Port": 443,
"AbsolutePath": "/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png",
"LocalPath": "/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png",
"Segments": [
"/",
"img/",
"PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png"
],
"Query": "?authorization=bce-auth-v1%2Fe8a94e73dad54d3a9",
"PathAndQuery": "/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png?authorization=bce-auth-v1%2Fe8a94e73dad54d3a9"
}
🔍 获取一个网络文件(图片)的文件名
string url = "https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png?authorization=bce-auth-v1%2Fe8a94e73dad54d3a95bb502a395696f3%2F2022-09-05T01";
//获取一个网络图片的文件名
var data = url.GetFileName();
// 输出 PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png
// 并更改文件扩展名
var data2 = url.GetFileName(".jpg");
// 输出 PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.jpg
💎 文件/图像操作
🔍 解压rar文件
// 解压rar文件
YokoFile.UnRar("rar源文件目录地址",'解压到哪?')
🔍简单的图片操作
//简单的图片操作
YokoFile.UrlToImage() // 通过Url获取到Image格式的文件
//YokoFile.ImageToBase64() // 根据http/https图片路径获取图片并转换为base64格式字符串
"WebImgUrl".ImageToBase64() // 把weburl图片转换为base64格式字符串 [1.6.2.8]
"base64编码".Base64ToImage() // 将Base64编码转换成图片
🔍生成缩略图
//生成缩略图
Image image = Image.FromFile(@"D:\Demo001.jpg");
image.ImageToThumbnail(@"D:\Demo001_1.jpg", 80, 50, CutMode.LockWidth);
🔍在图片上绘制文字
// 图片绘制
// 在图片上绘制文字
YokoFile.DrawStringWord(new DrawStyle
{
SourcePath = sourcePath, // 底图画布的路径
TargetPath = targetPath, // 保存图像的目标路径
TextContent = "Hello \n WoCao", // 文字内容
FamilyName = "宋体", // 字体
FontSize = 15, // 文字大小
Color = Color.White, // 颜色
X = 100, // 距左上角的 x 坐标
Y = 100, // 距左上角的 y 坐标
Width = 100, // 限定文本内容的宽
Height = 100 // 限定文本内容的高
});
🔍递归获取指定路径下的所有文件路径
// 递归获取指定路径下的所有文件路径
var path = "D:\\Demo";
foreach (var item in path.GetFilePath())
{
Console.WriteLine(item);
}
🔍 图片操作 jpeg、png 和 webp
从静态路径或者网络路径转换、调整大小和压缩 jpeg、png 和 webp 图像
💎 时间段操作
🔍 判断是否在某个时间段内、是否包含某个时间段、两个时间段是否相交、连接两个时间段
var range = new DateTimeRange("2021-9-3", "2021-9-5".ToDateTime());
//连接两个时间段,结果:2021-9-3~2021-9-6
range.Union("2021-9-4".ToDateTime(), "2021-9-6".ToDateTime());
//判断是否在某个时间段内,true
range.In("2021-9-3".ToDateTime(), "2021-9-6".ToDateTime());
//两个时间段是否相交,(true,2021-9-3~2021-9-4)
var (intersected,range2) = range.Intersect("2021-9-4".ToDateTime(), "2021-9-6".ToDateTime());
//判断是否包含某个时间段,true
range.Contains("2021-9-3".ToDateTime(), "2021-9-4".ToDateTime());
🔍 获取所有的补集时间段( 默认过滤差值为1min )
var range = new DateTimeRange(new DateTime(2021, 9, 3, 7, 8, 10)
, new DateTime(2021, 9, 4, 18, 0, 0));
Console.WriteLine($"时段:{range}");
Console.WriteLine();
Console.WriteLine();
var ranges = new List<DateTimeRange>()
{
new DateTimeRange(new DateTime(2021, 9, 3, 10, 0, 0), new DateTime(2021, 9, 3, 15, 0, 0)),
new DateTimeRange(new DateTime(2021, 9, 3, 20, 0, 0), new DateTime(2021, 9, 3, 23, 59, 59)),
new DateTimeRange(new DateTime(2021, 9, 4, 0, 0, 0), new DateTime(2021, 9, 4, 8, 0, 0)),
new DateTimeRange(new DateTime(2021, 9, 4, 12, 0, 0), new DateTime(2021, 9, 4, 18, 30, 59)),
new DateTimeRange(new DateTime(2021, 9, 10, 0, 0, 0), new DateTime(2021, 9, 10, 23, 59, 59))
};
var chargingPeriods = range.GetComplementPeriods(ranges, TimeSpan.FromMinutes(1));
foreach (var chargingPeriod in chargingPeriods)
{
Console.WriteLine($"补集时段:{chargingPeriod}");
}
🔍 判断时间段是否与一组时间段相交/包含,并返回所有相交/包含的时间段
var range = new DateTimeRange(new DateTime(2021, 9, 3, 7, 8, 10)
, new DateTime(2021, 9, 4, 18, 0, 0));
Console.WriteLine($"时段:{range}");
Console.WriteLine();
Console.WriteLine();
var ranges = new List<DateTimeRange>()
{
new DateTimeRange(new DateTime(2021, 9, 3, 10, 0, 0), new DateTime(2021, 9, 3, 15, 0, 0)),
new DateTimeRange(new DateTime(2021, 9, 3, 20, 0, 0), new DateTime(2021, 9, 3, 23, 59, 59)),
new DateTimeRange(new DateTime(2021, 9, 4, 0, 0, 0), new DateTime(2021, 9, 4, 8, 0, 0)),
new DateTimeRange(new DateTime(2021, 9, 4, 12, 0, 0), new DateTime(2021, 9, 4, 18, 30, 59)),
new DateTimeRange(new DateTime(2021, 9, 10, 0, 0, 0), new DateTime(2021, 9, 10, 23, 59, 59))
};
var freePeriods = range.IntersectWith(ranges);
foreach (var free in freePeriods)
{
Console.WriteLine($"相交/包含 时段:{free}");
}
💎 邮件发送
// 异步发送邮件 SendEmailAsync
// 同步发送 SendEmail
new Email()
{
SmtpServer = "smtp.qq.com",// SMTP服务器
SmtpPort = 587, // SMTP服务器端口
EnableSsl = true,//使用SSL
Username = "88888888888@qq.com",// 邮箱用户名
Password = "123456789",// 邮箱密码
Tos = "111111111@qq.com,22222222@qq.com", //多个收件人用,隔开
Subject = "测试邮件",//邮件标题
Body = "Hello,WoCao",//邮件内容
}.SendEmailAsync(s =>
{
// 发送成功后的回调
// 异步发送邮件,如果回调方法中参数不为"true"则表示发送失败
Console.WriteLine(s);
});
💎 雪花ID优化版
雪花算法实现方法有很多,它生成的ID更短、速度更快
可在单机或分布式环境生成数字型唯一ID,新增预留位,支持服务器时间回拨
兼容传统的经典雪花算法
🔍 调用示例
1、全局初始化,只需全局一次(必须在第2步之前设置)
//初始化 1.0.4+
YokoId.Init(1);
//================老版本================
//初始化
YokoId.SetIdGenerator(new IdGeneratorOptions(1));
//WorkerId [1,63]
2、生成ID
var newId = YokoId.NextId();
🔍 参数设置
- WorkerId,机器码,最重要参数,无默认值,必须 全局唯一,必须 程序设定,最大值63 特别提示:如果一台服务器部署多个独立服务,需要为每个服务指定不同的 WorkerId。
- WorkerIdBitLength,机器码位长,决定 WorkerId 的最大值,默认值6,取值范围 [1, 19]
💎 【已弃用】自动更新 IIS 上的 Asp.Net Core应用程序 2.1.1 ~ 2.2.0
- 通过上传 zip 文件,更新部署到正在IIS上运行的 Asp.Net Core 应用程序
注意事项:
1、将要发布更新的应用程序,全部 压缩打包成
publish.zip
文件2、zip 部署待更新文件应与站点位于同一位置。例如,
web.config
应该直接在 zip 文件内,而不是在 zip 文件内的文件夹内3、上传尽量使用临时文件名,直到上传完成,上传完成后再重命名为
publish.zip
4、上传完publish.zip后,会自动解压更新程序,并产生对应的临时文件。此时刷新应用程序,测试程序调用是否正常,临时文件会陆续自动删除
打开Startup.cs
using Yoko.Tool.ZipDeploy;
public void ConfigureServices(IServiceCollection services)
{
services.AddZipDeploy(c =>
{
//指定要忽略的文件或路径(例:"DebugLog.txt"、"Data"、"Log\Today")
c.IgnorePathStarting("Log");
c.IgnorePathStarting("Data");
});
······
}
💎 枚举操作
// 获取枚举对象Key与显示名称的字典
var dict = typeof(枚举类).GetDictionary();
// 获取枚举值对应的字符串
var enumStr = 0.ToEnumString(typeof(枚举类));
🍀更新日志
3.0.0-beta.1
【注意】部分结构破坏性更新,命名空间变化
【新增】重构的加密算法,并支持国密SM2,SM3,SM4
- AES,DES,RC4,TripleDES,RSA
- SM2,SM3,SM4
【新增】部分值类型操作
【新增】字符串相识度。对比字符串的汉明距离,汉明距离是编辑距离中的一个特殊情况,仅用来计算两个等长字符串中不一致的字符个数
【优化】 优化DataTable 转List、 DataTable 转实体性能
2.6.0-rc.3
【修复】修复方法 GetComplementPeriods
出现多余的值问题
2.6.0-rc.2
【修改】
- 判断时间段是否与一组时间段相交/包含,并返回所有相交/包含的时间段
IntersectWith
【新增】
- 获取所有的补集时间段( 默认过滤差值为1min )
GetComplementPeriods
var range = new DateTimeRange(new DateTime(2021, 9, 3, 7, 8, 10)
, new DateTime(2021, 9, 4, 18, 0, 0));
Console.WriteLine($"时段:{range}");
Console.WriteLine();
Console.WriteLine();
var ranges = new List<DateTimeRange>()
{
new DateTimeRange(new DateTime(2021, 9, 3, 10, 0, 0), new DateTime(2021, 9, 3, 15, 0, 0)),
new DateTimeRange(new DateTime(2021, 9, 3, 20, 0, 0), new DateTime(2021, 9, 3, 23, 59, 59)),
new DateTimeRange(new DateTime(2021, 9, 4, 0, 0, 0), new DateTime(2021, 9, 4, 8, 0, 0)),
new DateTimeRange(new DateTime(2021, 9, 4, 12, 0, 0), new DateTime(2021, 9, 4, 18, 30, 59)),
new DateTimeRange(new DateTime(2021, 9, 10, 0, 0, 0), new DateTime(2021, 9, 10, 23, 59, 59))
};
var chargingPeriods = range.GetComplementPeriods(ranges, TimeSpan.FromMinutes(1));
foreach (var chargingPeriod in chargingPeriods)
{
Console.WriteLine($"补集时段:{chargingPeriod}");
}
2.6.0-rc.1
【新增】 netstandard2.0;框架支持
【新增】判断时间段是否与一组时间段相交,并返回所有相交的时间段 IntersectWith
var range = new DateTimeRange(new DateTime(2021, 9, 3, 10, 5, 5)
, new DateTime(2021, 9, 4, 18, 12, 35));
var ranges = new List<DateTimeRange>()
{
new DateTimeRange(new DateTime(2021, 9, 3, 0, 0, 0), new DateTime(2021, 9, 3, 23, 59, 59)),
new DateTimeRange(new DateTime(2021, 9, 4, 0, 0, 0), new DateTime(2021, 9, 4, 15, 0, 0)),
new DateTimeRange(new DateTime(2021, 9, 4, 15, 0, 0), new DateTime(2021, 9, 4, 23, 59, 59)),
new DateTimeRange(new DateTime(2021, 9, 8, 0, 0, 0), new DateTime(2021, 9, 8, 23, 59, 59)),
new DateTimeRange(new DateTime(2021, 9, 10, 0, 0, 0), new DateTime(2021, 9, 10, 23, 59, 59))
};
var intersections = range.IntersectWith(ranges);
foreach (var intersection in intersections)
{
Console.WriteLine($"相交的时间段:{intersection.range}");
}
【新增】枚举操作:typeof(MyEnum).GetDescriptionItems
获取枚举值和描述的字典映射
枚举值必须携带 [Description("自定义")] [注意] 暂不支持根据枚举成员获取Display的属性Name
【优化】使用 AppVersion.Current
时,它将返回入口程序一个 不包含
元数据的版本号
【优化】使用 AppVersions.Current
时,它将返回入口程序一个 包含
元数据的版本号
【新增】递归获取指定路径下的所有文件路径 GetFilePath
【新增】将包含逗号分隔的字符串转换为 long 类型的数组:SplitCsvToLong
2.5.4
【新增】获取程序版本号 AppVersion.Current
2.5.3
Yoko.Tool.Core 移植功能
【新增】查询系统资源信息 (适合Windows和大部分的Linux发行版)
- SystemInfo.GetLocalIPAddress(); // 获取本机当前正在使用的IP地址
- SystemInfo.GetAllMacAddresses(); //获取本机所有MAC地址
- SystemInfo.GetOSVersion(); //获取操作系统版本
- SystemInfo.GetDriveSpaceInfo(); //获取所有硬盘的可用空间和总空间。单位:GB
- SystemInfo.GetMemorySpaceInfo(); //获取内存的可用空间和总空间。单位:GB
2.5.2
- 【优化】优化部分方法的异常提示及返回值
2.5.1
- 【优化】优化部分网络图片转Stream异常问题
2.5.0
【新增】URL 操作
1、分解URL信息
string url = "https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png?authorization=bce-auth-v1%2Fe8a94e73dad54d3a9"; // 分解URL信息 UrlSplit() var data = url.UrlSplit(); // 协议 data.Scheme; // 服务器地址 data.Host; // 端口号 data.Port; // 绝对路径 data.AbsolutePath; // 本地路径 data.LocalPath; // 路径的结构数组 data.Segments; // 查询信息部分 data.Query; // 问号(?) 分割后的部分 data.PathAndQuery;
json解读:
{ "Scheme": "https", "Host": "www.baidu.com", "Port": 443, "AbsolutePath": "/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png", "LocalPath": "/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png", "Segments": [ "/", "img/", "PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png" ], "Query": "?authorization=bce-auth-v1%2Fe8a94e73dad54d3a9", "PathAndQuery": "/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png?authorization=bce-auth-v1%2Fe8a94e73dad54d3a9" }
2、获取一个网络文件(图片)的文件名
string url = "https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png?authorization=bce-auth-v1%2Fe8a94e73dad54d3a95bb502a395696f3%2F2022-09-05T01"; //获取一个网络图片的文件名 var data = url.GetFileName(); // 输出 PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png // 并更改文件扩展名 var data2 = url.GetFileName(".jpg"); // 输出 PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.jpg
2.4.4
- 【新增】ASCII排序严格模式与非严格模式
2.4.3
【新增】日期时间的扩展
//返回标准时间格式(yyyy-MM-dd HH:mm:ss) DateTime.Now.GetDateTime(); // 获取该时间相对于1970-01-01 00:00:00的秒数 DateTime.Now.GetTotalSeconds(); // 获取该时间相对于1970-01-01 00:00:00的毫秒数 DateTime.Now.GetTotalMilliseconds();
2.4.2
- 【新增】DataTable 转 List、转 Model
2.4.1
- 【更新】修复OrderByASCII排序问题
2.4.0
【新增】恢复4.7.2、4.8 支持
【优化】缩减包体积,优化性能。移除对2.1.0的不停机更新支持,后续可能会单独发布包,如需使用,请保持2.1.0
2.2.0
- 【新增】枚举操作
2.1.1
- 【新增】将集合参数ASCII码从小到大排序 dict.OrderByASCII();
- 【新增】对集合进行分组ChunkList
- 【新增】求一个包含经纬度集合的距离和 YokoLngLat.GetDistanceSum(dict);
2.1.0
- 【新增】不停机更新。通过上传 zip 文件,更新部署到正在IIS上运行的 Asp.Net Core 应用程序
2.0.0
- 优化适配部分Net6特性方法
2.0之后不再支持 .NET Framework
1.6.2.8
- 新增支持对集合进行分组拆分为多个
- 优化ImageToBase64对部分格式图片不支持的问题、并更改调用方式
1.6.2.7
- 新增邮件发送
- Base64编码与图片互转
- 生成缩略图 (图像压缩请使用Yoko.Images.Webp)
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. |
.NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
.NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
.NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 is compatible. net48 is compatible. net481 was computed. |
MonoAndroid | monoandroid was computed. |
MonoMac | monomac was computed. |
MonoTouch | monotouch was computed. |
Tizen | tizen40 was computed. tizen60 was computed. |
Xamarin.iOS | xamarinios was computed. |
Xamarin.Mac | xamarinmac was computed. |
Xamarin.TVOS | xamarintvos was computed. |
Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETFramework 4.7.2
- BouncyCastle.Cryptography (>= 2.3.0)
- Newtonsoft.Json (>= 13.0.3)
- SharpCompress (>= 0.36.0)
- System.ComponentModel.Annotations (>= 5.0.0)
- System.Drawing.Common (>= 8.0.4)
- System.Management (>= 8.0.0)
-
.NETFramework 4.8
- BouncyCastle.Cryptography (>= 2.3.0)
- Newtonsoft.Json (>= 13.0.3)
- SharpCompress (>= 0.36.0)
- System.ComponentModel.Annotations (>= 5.0.0)
- System.Drawing.Common (>= 8.0.4)
- System.Management (>= 8.0.0)
-
.NETStandard 2.0
- BouncyCastle.Cryptography (>= 2.3.0)
- Newtonsoft.Json (>= 13.0.3)
- SharpCompress (>= 0.36.0)
- System.ComponentModel.Annotations (>= 5.0.0)
- System.Drawing.Common (>= 8.0.4)
- System.Management (>= 8.0.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last updated | |
---|---|---|---|
3.0.0-beta.1 | 71 | 4/22/2024 | |
2.6.0-rc.3 | 101 | 12/14/2023 | |
2.6.0-rc.2 | 90 | 12/14/2023 | |
2.6.0-rc.1 | 98 | 12/14/2023 | |
2.5.4 | 182 | 5/22/2023 | |
2.5.3 | 273 | 2/24/2023 | |
2.5.2 | 437 | 9/7/2022 | |
2.5.1 | 384 | 9/7/2022 | |
2.5.0 | 399 | 9/5/2022 | |
2.4.4 | 413 | 8/5/2022 | |
2.4.3 | 419 | 8/2/2022 | |
2.4.2 | 411 | 7/27/2022 | |
2.4.1 | 401 | 7/25/2022 | |
2.4.0 | 442 | 7/11/2022 | |
2.2.0 | 440 | 6/20/2022 | |
2.1.1 | 413 | 6/14/2022 | |
2.1.0 | 440 | 5/7/2022 | |
2.0.0 | 421 | 4/29/2022 | |
1.6.3 | 443 | 6/14/2022 | |
1.6.2.8 | 452 | 4/29/2022 | |
1.6.2.7 | 472 | 4/21/2022 | |
1.6.2.6 | 438 | 3/17/2022 | |
1.6.2.4 | 322 | 12/17/2021 | |
1.6.2.3 | 315 | 12/13/2021 | |
1.6.2.2 | 295 | 12/2/2021 | |
1.6.2.1 | 362 | 11/15/2021 | |
1.6.2 | 346 | 11/2/2021 | |
1.6.1.1 | 376 | 10/25/2021 | |
1.6.1 | 343 | 10/22/2021 | |
1.6.0.1 | 362 | 9/24/2021 | |
1.6.0 | 344 | 9/17/2021 | |
1.5.8.1 | 348 | 9/15/2021 | |
1.5.7 | 540 | 9/10/2021 | |
1.5.6 | 393 | 9/10/2021 | |
1.5.5 | 370 | 9/9/2021 | |
1.5.4 | 366 | 9/5/2021 | |
1.5.3 | 345 | 9/3/2021 | |
1.5.2 | 335 | 9/3/2021 | |
1.5.1 | 347 | 9/3/2021 | |
1.5.0 | 337 | 9/2/2021 | |
1.4.3 | 353 | 9/2/2021 | |
1.4.2 | 328 | 9/2/2021 | |
1.4.1 | 320 | 9/2/2021 | |
1.4.0 | 357 | 8/24/2021 | |
1.3.0 | 349 | 8/24/2021 |