C#.Net筑基-字符串超全总结

字符串是日常编码中最常用的引用类型了,可能没有之一,加上字符串的不可变性、驻留性,很容易产生性能问题,因此必须全面了解一下。


01、字符与字符编码

1.1、字符Char

字符 char 表示为 Unicode字符,在C#中用 UTF-16 编码表示,占用2个字节(16位)大小,字面量用单引号''包裹。

char c = 'A';
Console.WriteLine(char.IsDigit('3'));
Console.WriteLine(char.IsNumber('1'));
Console.WriteLine(char.IsLetter('A'));
Console.WriteLine(char.IsLower('a'));
Console.WriteLine(char.IsUpper('A'));
Console.WriteLine(char.GetUnicodeCategory('A')); //获取字符分类
  • char 是值类型(结构体),以16位整数形式存储,char可隐式转换为int
  • 字符串可以看做是char序列(数组),字符串是引用类型。

image.png

string str = "Hello World";
Console.WriteLine(str[0]);  //H
Console.WriteLine(str[10]); //d
Console.WriteLine(str[0].GetType().Name); //Char

1.2、字符集Unicode与字符编码

一般情况下字符串长度string.Length 就是可见的文本字符数量,但这并不绝对相等。大多数字符都是一个char组成,然而有些字符无法用一个char表示,如表情、不常用字符等,他们会用两个char(4个字节)来表示。

"a".Length.Dump();    //1
"🔊".Length.Dump();  //2
"🚩".Length.Dump();  //2
"⏰".Length.Dump();  //1
"你好".Length.Dump(); //2
"臢".Length.Dump();   //1
$"{(int)'A':X4}".Dump(); //0041
//上面的dump() 是一个扩展方法,作用同Console.WritLine()

Unicode 是国际标准、通用字符集,涵盖了世界上几乎所有的文字、符号,可以满足跨平台、跨语言的文本信息编码。Unicode 有100W+个字符地址空间,地址范围是 0x0000 - 0x10FFFF,每个字符都有自己的编码,目前已分配了大约10W+个。通常使用“U+”后跟一个十六进制数来表示,例如字母A的Unicode码点是U+0041

Unicode 字符集中包含多个分类(平面):其中最常用的就是基本平面,大部分常用字符都在这里面。

  • 🔸基本多文种平面(BMP,Basic Multilingual Plane):Unicode 的BMP区域几乎包含了所有常用的字符,如几十种主流语言,及30000+的汉字,BMP区域的字符都只需要1个char(2个字节)表示。
  • 🔸辅助平面(SMP):包含其他不常使用的字符,如一些历史文字、音乐符号、数学符号和表情符号等。该区域大多用两个char(4个字节)表示一个符号。

image.png

Unicode 是一种字符集,而实际在计算机上存储时需要用一个确定的编码方案,常见的就是UTF-8、UTF-16、UTF32。

  • UTF-16:2个字节表示BMP中的字符,其他字符会需要4个字节,C#、Java语言内部就是使用的UTF-16来表示的字符串。
  • UTF-8:变长编码,使用1到4个字节来表示一个Unicode字符,在互联网使用广泛。特别是存储 ASCII 为主的内容时,变长编码可以显著节约存储空间。

📢ASCII 字符集只包含 128个 基础字符,涵盖键盘上的字母、数字、常用符号。Unicode 是包含 ASCII字符集的,最前面128 个字符就是。在UTF-8编码中 ASCII字符只需要1个字节。


02、String基础

字符串 string 是一个不可变(不可修改)的字符序列(数组),为引用类型,字面量用双引号""包裹。

string s1 = "sam";
string s2 = new string('1',5);//11111
Console.WriteLine(s2[0]); //像数组一样操作字符串中的字符
string s3 = "";
string s4 = string.Empty; //效果同上
//相等比较
object s1= "Hello".Substring(0,2);
object s2 = "Hello".Substring(0,2);	
(s1==s2).Dump();        //False
(s1.Equals(s2)).Dump(); //True
  • 字符串是引用类型,因此可以用null表示,不过一般空字符建议用string.Empty(或"")表示。
  • 字符串可以当做 字符数组一样操作,只是不能修改。
  • 字符串的相等为值比较,只要字符序列相同即可。例外情况请是如果用object==比较,只会比较引用地址。

image.png

🚩 字符串在存储、转换为字节码时需指定编码,一般默认为 UTF-8,这是广泛使用的编码类型,更节省空间。

2.1、字符串常用API

属性特点/说明
Length字符串中字符数量
索引器[int index]索引器,用索引获取字符,不可修改
🔸方法特点/说明
StartsWith、EndsWith(String)判断开头、结尾是否匹配,"Hello".StartsWith("He")
Equals(String)比较字符串是否相同
IndexOf()查找指定字符(串)的索引位置,从后往前查找 LastIndexOf
Insert(Int32, String)指定位置插入字符串,‼️返回新字符串!
PadLeft(Int32)指定字符宽度(数量)对齐,左侧填充,‼️返回新字符串!右侧填充 PadRight(Int32)
Remove(Int32, Int32)删除指定位置、长度的字符,‼️返回新字符串!
Replace(String, String)替换指定内容的字符(串),‼️返回新字符串!
Substring(Int32, Int32)截取指定位置、长度的字符串,‼️返回新字符串!
ToLower()、ToUpper()返回小写、大写形式的字符串,‼️返回新字符串!
Trim()裁剪掉前后空格,‼️返回新字符串!有多个配套方法 TrimEnd、TrimStart
Split(char)按分隔符分割字符串为多个子串,比较常用,不过性能不好,建议用Span代替。
🔸静态方法特点/说明
Empty获取一个空字符串(同""
Compare(String, String)比较两个字符串,有很多重载,返回一个整数,0表示相同。
Concat (params string?[])连接多个字符串,返回一个新的字符串,有很多重载,是比较基础的字符串连接函数。
Equals(str, StringComparison)比较字符串是否相同,可指定比较规则 StringComparison
Format(String, Object[])字符串格式化,远古时期常用的字符串格式化方式,现在多实用$插值
string Intern(String)获取“内部”字符串,先检查字符串池中是否存在,有则返回其引用,没有则添加并返回
string? IsInterned(String)判断是否在字符串池中,存在则返回其引用,没有则返回null
IsNullOrEmpty(String)判断指定的字符串是否 null 、空字符""/String.Empty,返回bool
IsNullOrWhiteSpace(String)判断指定的字符串是否 null 、空字符""/String.Empty、空格字符,返回bool
Join(Char, String[])用分隔符连接一个数组为一个字符串

2.2、字符串的不变性、驻留性

字符串是一种有一点点特别的引用类型,因为其不变性,所以在参数传递时有点像值类型。

  • **🔸不变性:**字符串一经创建,值不可变。对字符串的各种修改操作都会创建新的字符串对象,这一点要非常重视,应尽量避免,较少不必要的内存开销。
  • 🔸驻留性:运行时将字符串值存储在“驻留池(字符串池)”中,相同值的字符串都复用同一地址。

不变性、驻留性 是.Net对string 的性能优化,提升字符串的处理性能。如下示例中,s1、s2字符串是同一个引用。

string s1 = "hello";
string s2 = "hello";
Console.WriteLine(s1 == s2);                      //True
Console.WriteLine(s1.Equals(s2));                 //True
Console.WriteLine(Object.ReferenceEquals(s1,s2)); //True

当然不是所有字符串都会驻留,那样驻留池不就撑爆了吗!一般只有两种情况下字符串会被驻留:

  • 字面量的字符串,这在编译阶段就能确定的“字符串常量值”。相同值的字符串只会分配一次,后面的就会复用同一引用。
  • 通过 string.Intern(string) 方法主动添加驻留池。

image.png

string st1 = "123" + "abc";
string st2 = "123abc";
string st3 = st2.Substring(0,3);

看看上面代码生成的IL代码:

image.png

  • 常量的字符串"123" + "abc"连接被编译器优化了。
  • 常量字符串使用指令“ldstr”加载的到栈,该指令会先查看驻留池中是否已存在,如果已存在则直接返回已有字符串对象的地址,否则就加入。

image.png

驻留的字符串(字符串池)在托管堆上存储,大家共享,内部其实是一个哈希表,存储被驻留的字符串和其内存地址。驻留池生命周期同进程,并不受GC管理,因此无法被回收。因此需要注意:

  • lock锁不能用string,避免使用同一个锁(字符串引用)。
  • 避免创建字面量的大字符串,会常住内存无法释放,当然也不要滥用string.Intern(string) 方法。

2.3、字符串的查找、比较

string 的 比较字符串 是默认包含文化和区分大小写的顺序比较,C#内置的一个字符串比较规则(枚举)StringComparison,可设置比较规则。在很多内置方法中使用,包括 String.Equals、String.Compare、String.IndexOf 和 String.StartsWith等。

📢 微软官方建议在使用上述字符串比较方法中明确指定 StringComparison 参数值,而不是默认的比较规则。

public enum StringComparison
{CurrentCulture,CurrentCultureIgnoreCase,InvariantCulture,InvariantCultureIgnoreCase,Ordinal,OrdinalIgnoreCase
}
void Main()
{string.Equals("ABC","abc",StringComparison.Ordinal);           //Faslestring.Equals("ABC","abc",StringComparison.OrdinalIgnoreCase); //Truestring.Compare("ABC","abc",StringComparison.Ordinal);          //-32string.Compare("ABC","abc",StringComparison.OrdinalIgnoreCase);//0
}
枚举值说明
CurrentCulture本地语言区域规则,适用于给用户显示的内容
CurrentCultureIgnoreCase同上+忽略大小写
InvariantCulture固定语言区域,适用于存储的数据
InvariantCultureIgnoreCase同上+忽略大小写
Ordinal二进制值顺序比较字符串,比较快⚡
OrdinalIgnoreCase同上+忽略大小写

如果单纯从性能角度考虑,考虑语言文化的字符串比较其实比较慢,来测试对比一下。测试代码:

string s1 = "hellohellohellohello";
string s2 = "helloHelloHelloHello";public bool Equals() => s1.Equals(s2);//Falsepublic bool Equals_CurrentCulture() => s1.Equals(s2,StringComparison.CurrentCulture);//False
public bool Equals_CurrentCultureIgnoreCase() => s1.Equals(s2,StringComparison.CurrentCultureIgnoreCase);//True
public bool Equals_InvariantCulture() => s1.Equals(s2,StringComparison.InvariantCulture);//False
public bool Equals_InvariantCultureIgnoreCase() => s1.Equals(s2,StringComparison.InvariantCultureIgnoreCase);//True
public bool Equals_Ordinal() => s1.Equals(s2,StringComparison.Ordinal);//False
public bool Equals_OrdinalIgnoreCase() => s1.Equals(s2,StringComparison.OrdinalIgnoreCase);//Truepublic bool Equals_Span() => s1.AsSpan() == s2.AsSpan();//False
  • 上面7个方法 分别测试了Equals的默认版本、及带参 StringComparison 的不同比较规则的性能。
  • 最后加了一个使用Span 的相等比较,更多关于Span的资料查看《高性能的Span、Memory》。

image.png

🚩测结结论

  • Span最快,其次无参Equals()版本、Ordinal,他们都是只比较二进制值,不考虑文化信息。
  • 个人理解,如果不考虑一些比较特别的语言(如瑞典语、土耳其语、 阿塞拜疆语等),只是针对英文、中文的字符串,一般不用考虑文化语义。
  • Equals()默认是不考虑文化语义的字符值比较,但有些比较方法就不一定能了,比如StartsWithCompare 默认的是带文化语义的CurrentCulture规则,因此推荐主动配置 StringComparison 参数。

2.4、字符串转义\

转义字符:反斜杠“\”

转义序列字符名称Unicode 编码
\'单引号0x0027
\"双引号0x0022
\0null0x0000
\bBackspace0x0008
\f换页0x000C
\n换行0x000A
\r回车0x000D
\t水平制表符0x0009

image.png


03、🚩字符串连接的8种方式

字符串连接(组装)的使用是非常频繁的,.Net中提供了多种姿势来实现,各有特点。

连接方法示例/说明
直接相加"hello"+str,其实编译后为 string.Concat ("hello", str)
连接函数:String.Concat()字符串相加一般就是被编译为调用String.Concat()方法,有很多重载,支持任意多个参数
集合连接函数:String.Join()将(集合)参数连接为一个字符串,string.Join('-',1,2,3); //1-2-3
格式化:String.Format()传统的字符串格式化手艺,string.Format("name:{0},age:{1}",str,18)
$ 字符串插值用花括号{var}引用变量、表达式,强大、方便,$"Hello {name} !"
@逐字文本字面量支持转义符号、换行符,常用于文件路径、多行字符:@$"C:\\Users\\{name}\\Downloads"
"""原始字符串字面量C# 11,三个双冒号包围,支持多行文本的原始字面量。
StringBuilder当处理大量字符串连接操作时,推荐使用StringBuilder,效果更优。

字面量字符串的相加会被编译器优化,直接合并为一个字符串。

var str1 = "Hello " + "world" + " !";
var str2 = DateTime.Now.Year + "年" + DateTime.Now.Month + "月";//编译后的代码:
string str1 = "Hello world !";
string str2 = string.Concat (DateTime.Now.Year.ToString (), "年", DateTime.Now.Month.ToString (), "月");

3.1、字符串格式化 String.Format

String.Format 方法是早期比较常用的字符串组织方式,后来$字符串插值 问世后就逐步被打入冷宫了。

string.Format("{0}+{1} = {2}",1,2,3);  //1+2 = 3
string.Format("Hello {0},{0}","sam");  //Hello sam,sam
String.Format("It is now {0:yyyy-MM-dd} at {0:hh:mm:ss}", DateTime.Now); //It is now 2024-01-17 at 10:56:33
String.Format("买了{0}个桔子,共花了{1:C2}。", 4,25.445); //买了4个桔子,共花了¥25.45。

基本语法规则就是用 {index}来占位,在后面的参数中给出值。

  • 索引位置从0开始,必须连续递增,可以重复。
  • 索引的位置对应后面参数的顺序位置,必须对应,参数不能少(抛出异常),可以多。
  • 字符串格式规则参考后文《字符串格式总结》。

3.2、$字符串插值

字符串插值的格式:$"{<interpolationExpression>}",大括号中可以是一个变量,一个(简单)表达式语句,还支持设置格式。功能强大、使用方便,老人孩子都爱用!

  • {}字符转义,用两个{{}}即可,如果只有一边,则用单引号'{{',即输出为{
  • 使用三元运算符?表达式,用括号包起来即可,因为“:”在插值字符串中有特殊含义,即格式化。
  • 字符串格式规则参考后文《字符串格式总结》。
var name = "sam";
Console.WriteLine($"Hello {name}!");  //Hello sam!
Console.WriteLine($"日期:{DateTime.Now.AddDays(1):yyyy-MM-dd HH:mm:ss}");  //日期:2024-01-18 23:21:55!
Console.WriteLine($"ThreadID:{Environment.CurrentManagedThreadId:0000}");  //ThreadID:0001
Console.WriteLine($"Length:{name.Length}");  //Length:3
Console.WriteLine($"Length:{(name.Length>3?"OK":"Error")}");  //Length:Error

3.3、@字符串支持任意字符

@标记的字符串为字面量字符串 ,不需要使用转义字符了,可搭配$字符串插值使用。文件路径地址都会用到@,两个冒号表示一个冒号,@"a""b" ==a"b

var path= @"D:\GApp\LINQPad 8\x64";
var file = $@"D:\GApp\LINQPad 8\x64\{DateTime.Now:D}";
var maxText = @"Hi All:第一行换行";

3.4、👍🏻StringBuilder

StringBuilder 字符串修理工程师,顾名思义,就是专门用来组装字符串的,可以看做是一个可变长字符集合。适用于把很多字符串组装到一起的场景,避免了大量临时字符串对象的创建,可显著提升性能。

var sb = new StringBuilder(100);
sb.Append("sam");
sb[0] = 'F';  //Fam
sb.AppendLine("age");
sb.Append("age").Append(Environment.NewLine); //效果同上
sb.Insert(2,"---");
sb.Replace("age","Age");var result = sb.ToString(); //获取结果
属性特点/说明
Capacity获取、设置字符容量(实际占用内存),默认16,当内容增多容量不足时,会自动扩容。
MaxCapacity获取最大容量,20亿字符
Length实际字符内容的长度,可赋值,设置0则清空已有字符内容,但并不影响 Capacity。
Chars[Int32]索引器,可获取、设置字符
🔸方法特点/说明
StringBuilder(Int32)构造函数,参数指定初始容量capacity
Append(value)追加字符,很多重载版本,类似还有AppendFormat、AppendJoin
AppendLine追加字符后,再追加一个换行符
Insert (int index, value)指定位置插入字符内容
Replace(Char, Char)查找替换字符(字符串)内容,会替换所有找到的字符内容
ToString()将 StringBuilder 输出为一个字符串,一般是StringBuilder的命运终点。
  • 各种Append方法都返回自身,可用来链式编程。
  • StringBuilder 默认容量为16,内部有一个char数组m_ChunkChars(缓冲区)来存储字符内容,如下StringBuilder构造函数源码:
public StringBuilder()
{m_MaxCapacity = int.MaxValue;m_ChunkChars = new char[16];
}
  • 当不断追加字符串,容量不足会自动扩容,扩容的过程其实就是创建更大的字符数组(容量翻倍),把原来的值拷贝过来,这个过程会涉及数组对象创建、内存拷贝。

📢 一般使用StringBuilder 建议尽量给一个合理的默认容量大小,尽量避免、减少频繁的扩容。


04、🚩字符串格式化大全

📢字符串格式语法:{index/interpolationExpression [,alignment][:formatString]}

  • ,alignment可选,设置字符串的对齐长度,如果位数不够则空格补齐,正数部补左边,负数补右边。
  • :formatString指定格式规则。一次只能指定一个格式规则,可和,alignment共存。
//,alignment 示例
var name = "sam";
$"name:{name,6}.";    //字符长度6,前面补齐空格 //name:   sam.
$"name:{name,-6}.";   //字符长度6,后面补齐空格 //name:sam   .
"1123+1 = {(1223+1),6:#,#.##}";                //1123+1 =  1,224
string.Format("1123+1 = {0,6:#,#.##}",1223+1); //1123+1 =  1,224

**4.1、**数值格式

🚩标准数值格式

🔸数值格式说明
E3/e3科学计数法(指数),数字"3"为小数精度,$"{12345.2:E3}" //1.235E+004,E+4表示10的4次方;如果是E-4则表示为小数(除以10的四次方) 1E-4 = 0.0001
F4定点格式,小数精度为"4",位数不够后面补0,支持所有数值类型,$"{123.22F:F4}" //123.2200
G4定点格式F+指数E的结合版,最多"4"个有效数字,超过就用科学计数法。"{123:G2}" //1.2E+02,$"{123:G4}" //123
C3货币格式(支持千分位),数字“3”为小数位数,$"{123.346:C2}" //¥123.35
P2百分比格式,数字乘以100后转换为百分数,数字“2”为小数位数,$"{0.2:P2}" //20.00%
N6数字格式化(支持千分位),小数位数为6,不够后面补0,$"{123:N6}" //123.000000
D6整数定长格式,不够前面补0,只支持整数,$"{123:D6}" //000123
B输出为二进制格式,仅支持整数+.Net8,精度为字符串位数,不够补0,$"{123:B}" //1111011
X/x输出为十六进制格式,仅支持整数+,精度为字符串位数,不够补0,$"{12:X4}" //000C

🚩自定义的数值格式

🔸数值格式符号说明
#数字占位符,不强制占位,$"{123:#,###.##}" //123
0数字(0)占位符,强制占位,不够补0。$"{123:0000.00}" //0123.00
.小数点,
,千分位,
,倍数符号,也是逗号,在末尾、小数点前为倍数符号,除以1000,可多个。$"{12000:#,}" //12
%百分数,乘一百+%,$"{0.2:00.00%}" //20.00%
E/e指数(科学计数),$"{10.1234:0.00e0}" //1.01e1;$"{0.01234:0.00e0}" //1.23e-2
\\转义字符,

📢热知识:小数格式化截断时都会四舍五入,(int)double 强转换是直接截断整数部分,相当于向下取整。 🔊冷知识:土耳其文化中的小数点为“逗号”,而非“点”。

4.2、日期时间格式

🔸日期格式-自定义说明(DateTime 和 DateTimeOffset
yyyy年份,yyyy //2024,yy //24
MM2位数的月份,1个M就不会补0 了,3/4个M为月份名称。M //4,MM //04,MMM //4月,MMMM //四月
dd2位数的日,3/4个d为星期。d //8,dd //08,ddd //周一,dddd //星期一
HH2位数的小时(24小时制)
hh2位数的小时(12小时制)
mm2位数的分钟
ss2位数的秒
f为1/10秒单位,ff为1/100秒单位,以此类推,fff就表示毫秒
ttAM/PM 指示符
组合使用以上可组合使用,可穿插任意字符,$"{DateTime.Now:yyyy年MM月dd日 HH:mm:ss}"
🔸日期格式-简写说明
D、dD长日期,d短日期,$"{DateTime.Now:D}" //2024年1月18日
F、f完整日期/时间模式,F长时间,f短时间,$"{DateTime.Now:F}" //2024年1月18日 22:45:34
T、tT长时间,t短时间,$"{DateTime.Now:T}" //22:45:42
M/m月日模式,$"{DateTime.Now:M}" //1月18日
Y/y年月模式,$"{DateTime.Now:Y}" //2024年1月

4.3、其他格式

🔸枚举格式说明
G/g,F/f枚举的字符串名称,其中F用于Flags,$"{UType.User:G}" //User
D/d十进制枚举值,$"{UType.User:D}" //2
X/x十六进制枚举值,$"{UType.User:X}" //00000002
🔸其他说明
IFormattable自定义的格式化接口,使用自定义的 IFormatProvider 来实现格式化输出ToString()
NumberStyles用于解析数字符串(Parse)时指定的解析格式
DateTimeStyles同上,用于时间日期的解析

🚩格式MSDN参考资料

  • 所有整型和浮点类型。 (请参阅 标准数字格式字符串 和 自定义数值格式字符串。)
  • DateTime 和 DateTimeOffset。 (请参阅 标准日期和时间格式字符串 和 自定义日期和时间格式字符串。)
  • 所有枚举类型。 (请参阅 枚举格式字符串.)
  • TimeSpan 值。 (请参阅 标准 TimeSpan 格式字符串 和 自定义 TimeSpan 格式字符串。)
  • GUID。 (请参阅 Guid.ToString(String) 方法。)

06、高性能字符串实践

提高string处理性能的核心就是:尽量减少临时字符串对象的创建

  • 高频常用字符串(非字面量)可考虑主动驻留字符串,string.Intern(name)
  • 字符串的比较、查找,优先用Span,或者尽量使用无文化语义的比较StringComparison.Ordinal
  • 大量字符串连接使用StringBuilder,且尽量给定一个合适的容量大小,避免频繁的扩容。
  • 少量字符串连接用字符串插值即可,创建StringBuilder也是有成本的。
  • 如果有大量StringBuilder 的使用,可以考虑用StringBuilderCache,或池化StringBuilder。

6.1、比较字符串

  • 字符串查找、拆分字符串、解析字符串,推荐使用Span,参考《高性能的Span、Memory》。
  • 查找、比较字符串,尽量指定 StringComparisonOrdinalOrdinalIgnoreCase,采用无文化特征的比较性能更快。
string str1="a",str2 = "b";
//这种方式会产生新的字符串,不推荐
if(str1.ToLower() == str2.ToLower()){} 
//推荐写法
if(string.Compare(str1, str2, true)==0){} 
if(string.Equals(str1,str2,StringComparison.Ordinal)){}

image.png

6.2、字符串真的不能修改吗?

字符串其实也是可以修改的,当然是用非常规手段。

  • ref获取指定字符的引用地址(指针地址)。
static void Main(string[] args)
{var str1 = "hello";var str2 = "hello";//修改第0位ref var c1 = ref MemoryMarshal.GetReference<char>(str1);c1 = 'H';//修改第一位ref var c2 = ref MemoryMarshal.GetReference<char>(str1.AsSpan(1));c2 = 'E';Console.WriteLine(str1);//输出:HElloConsole.WriteLine(str2);//输出:HEllo
}
  • 直接使用指针修改字符值。
void Main()
{var str1 = "hello";var str2 = "hello";unsafe{fixed (char* c = str2){c[0] = 'H';c[1] = 'E';}}Console.WriteLine(str1); //HElloConsole.WriteLine(str2); //HEllo
}

参考资料

  • C# 文档
  • 《C#8.0 In a Nutshell》
  • .NET面试题解析(03)-string与字符串操作
  • .NET 中的字符编码

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/61105.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

苍穹外卖-后端部分

软件开发整体介绍 前端搭建 在非中文目录中双击nginx.exe然后浏览器访问localhost即可 后端搭建 基础准备 导入初始文件 使用git进行版本控制 创建本地仓库和远程仓库,提交Git 连接数据库 连接数据库把资料中的文件放入运行即可 前后端联调测试 苍穹外卖项目接口文档…

剧本杀门店预约小程序,解锁沉浸式推理体验

一、开发背景 剧本杀作为一种热门娱乐游戏&#xff0c;深受大众的欢迎&#xff0c;但随着市场的快速发展&#xff0c;竞争也在不断加大&#xff0c;对于剧本杀线下商家来说面临着发展创新。 剧本杀线下门店数量目前正在逐渐增加&#xff0c;竞争激烈&#xff0c;而门店的获客…

【WPF】Prism学习(二)

Prism Commands 1.命令&#xff08;Commanding&#xff09; 1.1. ViewModel的作用&#xff1a; ViewModel不仅提供在视图中显示或编辑的数据&#xff0c;还可能定义一个或多个用户可以执行的动作或操作。这些用户可以通过用户界面&#xff08;UI&#xff09;执行的动作或操作…

学者观察 | 元计算、人工智能和Web 3.0——山东大学教授成秀珍

导语 成秀珍教授提出元计算是在开放的零信任环境下整合算力资源打通数据壁垒构建自进化智能的新质生产力技术&#xff0c;是一种新计算范式&#xff1b;区块链是Web3.0的核心技术之一&#xff0c;有助于保障开放零信任环境下&#xff0c;用户、设备和服务间去中心化数据流通的…

学习笔记022——Ubuntu 安装 MySQL8.0版本踩坑记录

目录 1、查看可安装 MySQL 版本 2、Ubuntu安装 MySQL8.0 3、MySQL8.0 区分大小写问题 4、MySQL8.0 设置sql_mode 5、MySQL8.0 改端口33060&#xff08;个人遇到问题&#xff09; 1、查看可安装 MySQL 版本 ## 列出可用的MySQL版本&#xff08;列出所有可用的MySQL版本以…

「AI Infra 软件开源不是一个选项,而是必然」丨云边端架构和 AI Infra专场回顾@RTE2024

在人工智能和开源技术蓬勃发展的当下&#xff0c;AI Infra 项目正经历着日新月异的变革。从跨平台运行时到云边端 AI 基础设施&#xff0c;再到多模态知识助手&#xff0c;创新浪潮席卷而来。这些进步不仅显著提升了技术指标&#xff0c;也为实时音视频处理、边缘计算、大模型应…

《Python制作动态爱心粒子特效》

一、实现思路 粒子效果&#xff1a; – 使用Pygame模拟粒子运动&#xff0c;粒子会以爱心的轨迹分布并运动。爱心公式&#xff1a; 爱心的数学公式&#xff1a; x16sin 3 (t),y13cos(t)−5cos(2t)−2cos(3t)−cos(4t) 参数 t t 的范围决定爱心形状。 动态效果&#xff1a; 粒子…

免费实时图片编辑工具:MagicQuill

参看&#xff1a; https://huggingface.co/spaces/AI4Editing/MagicQuill 人工智能交互式图像编辑&#xff1a;可以制定涂改增加删除

web——upload-labs——第九关——特殊字符::$DATA绕过

特殊字符::$DATA绕过 典型绕过场景 在一些系统中&#xff0c;::$DATA 被用于绕过文件路径的限制。比如&#xff1a; 路径过滤绕过&#xff1a;如果系统有某种机制来检查和限制文件路径&#xff08;例如&#xff0c;禁止访问某些系统目录或敏感文件&#xff09;&#xff0c;通…

本地部署 excalidraw

本地部署 excalidraw 0. 引言1. 本地部署 excalidraw2. 访问 excalidraw 0. 引言 Excalidraw 编辑器是一款开源虚拟手绘白板&#xff0c;支持协作且端到端加密。 1. 本地部署 excalidraw git clone https://github.com/excalidraw/excalidraw.git; cd excalidrawvi docker-c…

《Java核心技术 卷I》用户界面AWT事件继承层次

AWT事件继承层次 EventObject类有一个子类AWTEvent&#xff0c;它是所有AWT事件类的父类。 Swing组件会生成更多其他事件对象&#xff0c;都直接拓展自EventObject而不是AWTEvent。 AWT将事件分为底层(low-level)事件和语义事件。 语义事件&#xff1a;表示用户的动作事件&…

三周精通FastAPI:42 手动运行服务器 - Uvicorn Gunicorn with Uvicorn

官方文档&#xff1a;Server Workers - Gunicorn with Uvicorn - FastAPI 使用 fastapi 运行命令 可以直接使用fastapi run命令来启动FastAPI应用&#xff1a; fastapi run main.py如创建openapi.py文件&#xff1a; from fastapi import FastAPIapp FastAPI(openapi_url&…

整理iPhone空间:iphone怎么删除相簿

随着时间的积累&#xff0c;我们的iPhone中不仅会堆积大量照片&#xff0c;还可能会有多个不再需要的相簿。这些相簿不仅占用存储空间&#xff0c;还可能使相册应用变得杂乱无章。本文将探讨iphone怎么删除相簿&#xff0c;并介绍精简iPhone相册的技巧&#xff0c;使你的相册管…

路漫漫其修远兮,吾将上下而求索---第一次使用github的过程记录和个人感受

文章目录 1.仓库位置2.新建仓库3.配置仓库4.克隆和上传5.推荐文章和我的感受 1.仓库位置 这个仓库的位置就是在我们的这个个人主页的右上角&#xff1b;如果是第一次注册账号的话&#xff0c;这个主页里面肯定是不存在仓库的&#xff0c;需要我们自己手动的进行创建&#xff1…

ICML24最新开源时序基础模型MOMENT

论文标题&#xff1a;MOMENT: A Family of Open Time-series Foundation Models 论文链接&#xff1a;https://arxiv.org/pdf/2402.03885 前言 当前时间序列数据上预训练大型模型面临以下挑战&#xff1a;(1) 缺乏大型且统一的公共时间序列数据集&#xff0c;(2) 时间序列特…

SpringBoot Data Redis连接Redis-Cluster集群

使用SpringBoot Data Redis无法连接Redis-Cluster集群 最近在研究系统高并发下的缓存架构&#xff0c;因此自己在自己买的云服务器上搭建好Redis 5.0 版本的集群后&#xff0c;使用springboot的 RedisTemplate连接是发现总是访问不到集群节点。上网百度了发现没有好的解决办法&…

鸿蒙中服务卡片数据的获取和渲染

1. 2.在卡片中使用LocalStorageProp接受传递的数据 LocalStorageProp("configNewsHead") configNewsHeadLocal: ConfigNewsHeadInfoItem[] [] 注意&#xff1a;LocalStorageProp括号中的为第一步图片2中的键 3.第一次在服务卡片的第一个卡片中可能会获取不到数据…

ARM64环境部署EFK8.15.3收集K8S集群容器日志

环境规划 主机IP系统部署方式ES版本CPU架构用户名密码192.168.1.225Ubuntu 22.04.4 LTSdockerelasticsearch:8.15.3ARM64elasticllodyi4TMmZD ES集群部署 创建持久化目录(所有节点) mkdir -p /data/es/{data,certs,logs,plugins} mkdir -p /data/es/certs/{ca,es01}服务器…

应用系统开发(12) Zync中实现数字相敏检波

在 Xilinx Zynq 系列(如 Zynq-7000 或 Zynq UltraScale+)中实现数字相敏检波(DSP,Digital Synchronous Detection)可以通过硬件(PL部分,FPGA逻辑)和软件(PS部分,ARM Cortex-A 处理器)的协同工作来实现。以下是一个详细的设计方法,包括基本原理和 Zynq 的实现步骤。…

力扣hot100-->二分查找

目录 二分查找 1. 33. 搜索旋转排序数组 2. 34. 在排序数组中查找元素的第一个和最后一个位置 3. 240. 搜索二维矩阵 II 3. 287. 寻找重复数 二分查找 1. 33. 搜索旋转排序数组 中等 整数数组 nums 按升序排列&#xff0c;数组中的值 互不相同 。 在传递给函数之前&am…