自由学习记录(28)
C# 中的流(Stream
)
流(Stream
)是用于读取和写入数据的抽象基类。
流表示从数据源读取或向数据源写入数据的矢量过程。
C# 中的流类是从 System.IO.Stream
基类派生的,提供了多种具体实现,每种实现都针对不同的数据源或用途。下面是一些常见的流类型及其作用:
流类型一般都被整合成了一个对象既管输入流 也管输出流,基础概念中的Stream也是如此,只不过有输入输出两个细分的类概念而已
1. 流的基础概念
- 流(Stream):在计算机中表示一种数据的连续流动,可以是从文件、内存、网络或其他设备中读取数据,或者将数据写入这些设备。
- 输入流(InputStream):用于从数据源读取数据。
- 输出流(OutputStream):用于将数据写入到数据源。
2. 常见的流类型
- FileStream:用于从文件读取或向文件写入数据。
- MemoryStream:用于在内存中读写数据,适用于不需要持久化的临时数据处理。
- NetworkStream:用于网络通信,处理通过网络传输的数据。
- BufferedStream:为其他流提供缓冲,以提高读取和写入性能。
- StreamReader 和 StreamWriter:用于处理文本数据的读写操作,通常与其他流(如
FileStream
)一起使用。 - CryptoStream:用于加密和解密数据流。
- GZipStream 和 DeflateStream:用于压缩和解压缩数据流。
3. 内存流(MemoryStream)
- 作用:
MemoryStream
是一个特殊的流,它将数据存储在内存中,而不是在磁盘上或其他外部设备上。适用于处理需要快速读写的临时数据。 - 特点:
- 读写速度快,因为数据存储在内存中。
- 用于在应用程序内部传输数据或在不需要长期存储数据时使用。
- 可以使用
ToArray()
方法将内存流中的数据转换为字节数组。
- 示例用法:
using System; using System.IO;class Program {static void Main(){// 创建一个内存流using (MemoryStream memoryStream = new MemoryStream()){// 写入数据到内存流byte[] data = new byte[] { 1, 2, 3, 4, 5 };memoryStream.Write(data, 0, data.Length);// 读取数据memoryStream.Position = 0; // 重置位置,以便读取byte[] readData = new byte[data.Length];memoryStream.Read(readData, 0, readData.Length);Console.WriteLine("Read data: " + string.Join(", ", readData));}} }
4. 文件流(FileStream)
- 作用:
FileStream
是用于从文件读取或向文件写入数据的流。它可以处理大文件的读写操作,并支持同步和异步操作。 - 特点:
- 适用于需要持久化存储数据的场景。
- 可以通过
FileStream
进行大容量文件的读写操作。 - 支持指定读取和写入的起始位置及长度。
- 示例用法:
using System; using System.IO;class Program {static void Main(){// 创建或打开文件进行写入using (FileStream fileStream = new FileStream("example.txt", FileMode.Create)){byte[] data = new byte[] { 1, 2, 3, 4, 5 };fileStream.Write(data, 0, data.Length);}// 读取文件数据using (FileStream fileStream = new FileStream("example.txt", FileMode.Open)){byte[] readData = new byte[fileStream.Length];fileStream.Read(readData, 0, readData.Length);Console.WriteLine("Read data from file: " + string.Join(", ", readData));}} }
5. 内存流与文件流的角色
- 内存流:适用于快速存储和处理临时数据。由于数据存在内存中,操作速度较快。适合数据量较小、需要在程序运行期间使用的数据(如缓存)。
- 文件流:用于处理需要持久化存储的数据,或者需要对较大文件进行读写的场景。它适合从文件中读取数据或将数据写入到文件的情况。
6. 内存流与文件流的比较
- 速度:内存流速度较快,因为数据在内存中。文件流通常慢一些,因为数据需要通过磁盘进行读写。
- 存储:内存流的数据是临时的,只在内存中存在。文件流的数据持久化存储在磁盘中。
- 使用场景:
- 内存流:适用于处理小到中等大小的数据或需要快速操作的数据,如临时数据的缓存。
- 文件流:适用于处理大文件或需要长期存储的文件,如日志文件、文档、数据库文件等。
总结
- 内存流(
MemoryStream
):在内存中读写数据,适合处理临时数据和高效的数据操作。 - 文件流(
FileStream
):用于文件读写,适合需要持久化存储的场景,支持大文件处理。
内存流和序列化
MemoryStream
内存中读写数据,一个流对象
序列化 对象转换为可以存储或传输的格式
结合这两个概念,你可以将对象序列化为字节流,并在内存中操作它们。
以下是一些常见的方法来实现内存流序列化:
1. BinaryFormatter
二进制序列化
.NET 中一个常用的序列化工具,可将对象转换为二进制格式,并将其写入流中。
示例代码:
using System;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;[Serializable]
public class MyClass
{public string Name { get; set; }public int Age { get; set; }
}class Program
{static void Main(){// 创建对象MyClass obj = new MyClass { Name = "Alice", Age = 30 };// 将对象序列化到内存流中using (MemoryStream memoryStream = new MemoryStream()){IFormatter formatter = new BinaryFormatter();formatter.Serialize(memoryStream, obj);// 将内存流的字节数组用于其他操作,例如保存到文件或传输byte[] serializedData = memoryStream.ToArray();// 反序列化对象using (MemoryStream readStream = new MemoryStream(serializedData)){MyClass deserializedObj = (MyClass)formatter.Deserialize(readStream);Console.WriteLine($"Name: {deserializedObj.Name}, Age: {deserializedObj.Age}");}}}
}
注意:BinaryFormatter
已被标记为不推荐使用,因为它存在安全风险,特别是在处理不受信任的数据时。建议使用其他序列化方法,如 System.Text.Json
或 XmlSerializer
。
2. 使用 JsonSerializer
进行 JSON 序列化
如果你希望使用更现代且安全的序列化格式,可以使用 System.Text.Json.JsonSerializer
。
示例代码:
using System;
using System.IO;
using System.Text.Json;public class MyClass
{public string Name { get; set; }public int Age { get; set; }
}class Program
{static void Main(){// 创建对象MyClass obj = new MyClass { Name = "Alice", Age = 30 };// 将对象序列化为 JSON 格式using (MemoryStream memoryStream = new MemoryStream()){JsonSerializer.Serialize(memoryStream, obj);memoryStream.Position = 0; // 重置流的位置,以便读取数据// 反序列化对象MyClass deserializedObj = JsonSerializer.Deserialize<MyClass>(memoryStream);Console.WriteLine($"Name: {deserializedObj.Name}, Age: {deserializedObj.Age}");}}
}
3. 使用 XmlSerializer
进行 XML 序列化
如果你需要序列化为 XML 格式,可以使用 XmlSerializer
。
示例代码:
using System;
using System.IO;
using System.Xml.Serialization;public class MyClass
{public string Name { get; set; }public int Age { get; set; }
}class Program
{static void Main(){// 创建对象MyClass obj = new MyClass { Name = "Alice", Age = 30 };// 将对象序列化为 XML 格式using (MemoryStream memoryStream = new MemoryStream()){XmlSerializer serializer = new XmlSerializer(typeof(MyClass));serializer.Serialize(memoryStream, obj);memoryStream.Position = 0; // 重置流的位置,以便读取数据// 反序列化对象MyClass deserializedObj = (MyClass)serializer.Deserialize(memoryStream);Console.WriteLine($"Name: {deserializedObj.Name}, Age: {deserializedObj.Age}");}}
}
总结
- 使用
BinaryFormatter
进行二进制序列化和反序列化。 - 使用
System.Text.Json.JsonSerializer
进行 JSON 格式的序列化和反序列化,推荐用于现代应用。 - 使用
XmlSerializer
进行 XML 格式的序列化和反序列化。
在选择序列化方法时,请根据你的需求和数据的安全性考虑。BinaryFormatter
不推荐用于处理不可信数据,而 System.Text.Json
和 XmlSerializer
更加安全和现代。
特性(Attributes)
每一个特性实例都是贴在挂了[] 的元素
这个元素可以在运行时通过反射调用特性类实例中的各种成员和方法
这些方法又可以反过来作用于挂[]的元素上,
比如特性挂在了某个类的方法上,那么每次调用这个方法的话
都是经过了挂在这个方法上的特性类实例的处理后,再产生最终结果的
不严谨,有错误的理解,但大致思路是这样的,只是这个处理应该不是在运行时动态的,还会扯到框架什么什么的,只不过目前的水平还深入不下去,目前这样理解也勉强凑合了
自己定义了一个特性类,这个特性类只要被挂在任意的一个元素上面,就会生成一个与这个元素相关联的特性类实例
类和方法的特性互不影响
-
类上的特性 只会影响类本身,与类中的方法、属性无关。
-
方法上的特性 只会影响该方法,与类的其他成员无关。
一个元素可以有多个特性。在 C# 中,多个特性可以作用在同一个类、方法、属性等元素上,每个特性会独立存在,且互不影响。
一个继承了 Attribute
的类可以被写成 []
中的特性语法,并附加到方法、属性、类等代码元素上
当你将特性应用到代码元素时,编译器会将特性实例的信息记录到元数据中,而不会直接在运行时创建该特性实例。
自建特性类的特性AttributeUsage
的参数
-
AttributeTargets
:指定可以应用特性的位置(类、方法、属性等)。 -
AllowMultiple
:是否允许同一代码元素上应用多个实例。 -
Inherited
:是否允许特性从基类继承。
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)]
public class MyCustomAttribute : Attribute
{public string Info { get; }public MyCustomAttribute(string info){Info = info;}
}
特性是通过反射获取的,不会直接附加到代码元素实例上。
加上特性之后,只有通过反射机制才能获得该特性的实例。
Type type = typeof(ExampleClass);
var attributes = type.GetCustomAttributes(typeof(MyCustomAttribute), false);
if (attributes.Length > 0)
{// 特性实例MyCustomAttribute myAttr = (MyCustomAttribute)attributes[0];Console.WriteLine($"Name: {myAttr.Name}, Version: {myAttr.Version}");
}
特性(Attributes) ,元编程机制,向代码元素(如类、方法、属性等)附加元数据。
这种元数据可以在运行时通过反射读取,并驱动额外的逻辑行为。
特性的原理
-
特性是类的实例
-
特性本质上是从
System.Attribute
派生的类
-
-
特性的声明方式:
-
特性类必须继承自
System.Attribute
。 -
特性通常通过
[AttributeUsage]
特性限制它可以应用的位置和次数。 -
特性可以有构造函数和属性,用于设置参数和配置。
-
特性如何工作
1. 编译时:将元数据嵌入到程序集
当你在代码中添加一个特性时,例如:
[Serializable]
public class MyClass { }
编译器会在程序集的元数据中为 MyClass
记录 Serializable
特性。
2. 运行时:通过反射读取特性
你可以在运行时通过反射读取特性的信息,并基于这些信息执行特定操作。
特性的创建与使用
1. 自定义特性
以下是自定义特性的示例:
using System;[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)]
public class MyCustomAttribute : Attribute
{public string Name { get; }public int Version { get; }public MyCustomAttribute(string name, int version){Name = name;Version = version;}
}
2. 应用特性
将特性应用到类或方法上:
[MyCustomAttribute("ExampleClass", 1)]
public class Example
{[MyCustomAttribute("ExampleMethod", 2)]public void TestMethod(){Console.WriteLine("Hello from TestMethod");}
}
3. 读取特性
通过反射读取特性的信息:
using System;
using System.Reflection;class Program
{static void Main(){// 获取类的特性Type type = typeof(Example);var classAttributes = type.GetCustomAttributes<MyCustomAttribute>();foreach (var attr in classAttributes){Console.WriteLine($"Class: {type.Name}, Name: {attr.Name}, Version: {attr.Version}");}// 获取方法的特性MethodInfo method = type.GetMethod("TestMethod");var methodAttributes = method.GetCustomAttributes<MyCustomAttribute>();foreach (var attr in methodAttributes){Console.WriteLine($"Method: {method.Name}, Name: {attr.Name}, Version: {attr.Version}");}}
}
输出:
Class: Example, Name: ExampleClass, Version: 1
Method: TestMethod, Name: ExampleMethod, Version: 2
为什么特性可以实现“奇奇怪怪”的功能?
1. 编译器的内置支持
许多特性(如 [Serializable]
, [Obsolete]
)在编译器中被特殊处理:
[Serializable]
:提示编译器生成支持序列化的代码。[Obsolete]
:在编译时发出警告或错误,提醒使用者该代码已经过时。
2. 框架和库通过特性扩展功能
特性可以驱动框架的运行行为。例如:
- ASP.NET Core 使用特性(如
[HttpGet]
,[HttpPost]
)标记控制器的路由规则。 - Entity Framework 使用特性(如
[Key]
,[Required]
)定义数据库表的映射规则。 - JSON 序列化库 使用特性(如
[JsonIgnore]
,[JsonProperty]
)控制对象的序列化行为。
3. 特性允许插入元编程逻辑
特性是实现 AOP(面向切面编程) 的核心工具,可以在特定代码执行时插入行为。例如:
[Log]
特性可以自动记录方法的调用信息。[Validate]
特性可以在方法调用前校验参数。
总结:特性的工作流程
- 声明特性:通过继承
System.Attribute
定义自定义特性。 - 应用特性:将特性以
[AttributeName]
的形式附加到代码元素上。 - 元数据存储:编译器将特性信息存储在程序集的元数据中。
- 读取特性:运行时通过反射获取元数据,执行逻辑。
特性看似只是加了个 []
,实际上背后依赖了 C# 的强大编译器支持和运行时反射机制,使得它能够驱动复杂的逻辑,成为元编程的重要工具。
Encoding.UTF8.GetString()
将字节数组(byte[]
)解码为字符串。
两种重载
1. 方法签名
重载1:直接传入字节数组
public string GetString(byte[] bytes);
重载2:指定范围
public string GetString(byte[] bytes, int index, int count);
- 参数说明:
byte[] bytes
: 要解码的字节数组。int index
: 哪个索引开始解码。int count
: 解码的字节数。
2. 用法示例
解码整个字节数组
using System;
using System.Text;class Program
{static void Main(){byte[] utf8Bytes = { 72, 101, 108, 108, 111 }; // "Hello" 的 UTF-8 编码string result = Encoding.UTF8.GetString(utf8Bytes);Console.WriteLine(result); // 输出: Hello}
}
解码部分字节
using System;
using System.Text;class Program
{static void Main(){byte[] utf8Bytes = { 72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100 }; // "Hello World" 的 UTF-8 编码// 解码从索引 6 开始的 5 个字节string result = Encoding.UTF8.GetString(utf8Bytes, 6, 5);Console.WriteLine(result); // 输出: World}
}
3. 参数的关键点
参数合法性
- 字节数组 (
byte[]
) 必须是合法的 UTF-8 数据:- 数组中包含非法或不完整的 UTF-8 字节序列,
GetString
会抛出异常或替换为 Unicode 替代字符(通常是�
)。
- 数组中包含非法或不完整的 UTF-8 字节序列,
- 索引和长度合法性:
index
和count
必须满足:index >= 0
count >= 0
index + count <= bytes.Length
- 否则会抛出
ArgumentOutOfRangeException
。
常用场景
- 解码整个字节数组:
Encoding.UTF8.GetString(bytes)
- 解码部分数据(如网络流数据或文件流数据的片段):
Encoding.UTF8.GetString(bytes, index, count)
4. 为什么有两种重载?
- 第一种重载适合解码完整的字节数组,简单直接。
- 第二种重载提供灵活性,允许你仅解码字节数组的一部分,这在处理大文件或流式数据时非常有用。
5. 总结
- 第一种重载(整个字节数组):
GetString(byte[] bytes)
解码完整数组,常见于静态数据的解码。 - 第二种重载(部分字节数组):
GetString(byte[] bytes, int index, int count)
解码字节数组的指定部分,适合处理流式数据或分块操作。
fs.Write()
FileStream
类提供,将数据写入文件。
文件流基于字节bytes
所有参数都是必需的,并且没有提供默认值
参数定义了写入的数据以及写入的范围,具体如下:
public override void Write(byte[] array, int offset, int count);
-
byte[] array
:写入文件的数据 -
int offset
:写入数据的起始索引(array[offset]
开始写入) -
int count
:- 指定
bytes数组
中写入的字节数。 - 这个参数可以限制实际写入的数据长度,即使字节数组长度大于
count
,也只会写入指定数量的字节。
- 指定
示例代码
using System;
using System.IO;class Program
{static void Main(){// 创建字节数据byte[] data = new byte[] { 65, 66, 67, 68, 69 }; // 对应 ASCII 字符 A, B, C, D, E// 打开文件流(会覆盖现有内容)using (FileStream fs = new FileStream("example.txt", FileMode.Create, FileAccess.Write)){// 写入 data 数组中的前 3 个字节(A, B, C)fs.Write(data, 0, 3);}Console.WriteLine("写入完成!");}
}
输出到 example.txt
的内容:
ABC
关键点补充
为什么不提供默认参数?
设计上,fs.Write()
是低级别的 I/O 方法,用于操作任意二进制数据。它的三个参数控制了写入的范围和数据来源,以下是设计理念:
- 灵活性:
offset
和count
允许你仅写入字节数组的一部分,而不是整个数组。 - 效率:你可以通过精确控制写入范围来优化性能,避免不必要的字节拷贝。
- 防止错误:如果默认写入整个数组,可能导致意外写入多余数据。
如何简化操作?
大多数常见的用法可以显式写成:fs.Write(data, 0, data.Length);
使用 BinaryWriter
BinaryWriter
是一个更高层的封装,简化了写入数据的操作,无需明确指定 offset
和 count
。它会直接将完整的字节数组写入文件:
using (var fs = new FileStream("example.txt", FileMode.Create, FileAccess.Write))
using (var writer = new BinaryWriter(fs))
{byte[] data = new byte[] { 65, 66, 67 }; // ABCwriter.Write(data); // 自动写入整个数组
}
使用 StreamWriter
(适用于文本数据)
如果处理的是文本而不是二进制数据,StreamWriter
更适合,它完全隐藏了底层字节操作:
using (var writer = new StreamWriter("example.txt"))
{writer.Write("Hello, World!"); // 写入文本
}
byte[] array
- 文件流操作是以字节为单位,需要将任何数据(如文本、数字、图像)转换为字节数组。
- 常见的转换方法:
- 字符串 转换为字节数组:
Encoding.UTF8.GetBytes(string)
- 数值类型 转换为字节数组:
BitConverter.GetBytes(int)
- 字符串 转换为字节数组:
offset
和 count
- 通过
offset
和count
参数可以选择性地从字节数组中提取一部分数据写入文件。 - 示例:
byte[] data = { 65, 66, 67, 68, 69 }; // A, B, C, D, E fs.Write(data, 2, 2); // 从索引 2 开始写入 2 个字节 -> 写入 "CD"
性能优化
- 数据量较大,使用
fs.Write()
尽量批量写入而不是逐字节写入 - 能减少 I/O 操作次数,提升性能
常见错误
-
数组越界:
- 如果
offset + count > array.Length
,会抛出ArgumentException
。 - 在使用前检查数组长度以避免错误:
if (offset + count > data.Length)throw new ArgumentException("指定的范围超出了数组长度!");
- 如果
-
流未打开或已关闭:
- 如果文件流在调用
Write()
时已关闭,ObjectDisposedException
会被抛出。
- 如果文件流在调用
-
权限不足:
- 如果文件流是只读模式(
FileAccess.Read
),会抛出NotSupportedException
。
- 如果文件流是只读模式(
移动会把文件夹里的所有东西一起移动过去
File.ReadAllLines()
File.ReadAllText()
File.Delete()
File.Copy()
File.Replace()
Application.dataPath
相关文章:
自由学习记录(28)
C# 中的流(Stream) 流(Stream)是用于读取和写入数据的抽象基类。 流表示从数据源读取或向数据源写入数据的矢量过程。 C# 中的流类是从 System.IO.Stream 基类派生的,提供了多种具体实现,每种实现都针对…...
HarmonyOS开发:关于签名信息配置详解
目录 前言 签名信息的重要性 签名的方式 自动化签名 1、连接真机 2、选择 手动签名 (一)生成密钥和证书请求文件 (二)申请调试证书 (三)注册调试设备 (四)申请调试Profil…...
react 组件双向绑定
1. 使用 state 实现双向绑定 对于双向绑定,需要同时处理表单元素的value属性(通过state来设置)和onChange事件(用于更新state)。 import { useState } from "react";const MyComponent () > {const [i…...
k8s api对象,CRD
在Kubernetes项目中,一个API对象在Etcd里的完整资源路径,是由:Group(API组)、Version(API版本)和Resource(API资源类型)三个部分组成 apiVersion: batch/v2alpha1 kind:…...
详解MyBatis之篇一
目录 MyBatis 定义 使用MyBatis操作数据库 创建项目 配置 演示 UserInfo.java UserInfoMapper UserInfoMapperTest 数据准备 自动生成测试类 运行结果 MyBatis 定义 MyBatis 是一个优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避…...
uniapp连接mqtt频繁断开原因和解决方法
mqtt参考文档:MQTT.js 入门教程 | EMQ、MQTT.js 入门教程 - EMQX - 博客园 uniapp引用MQTT频繁断开的问题可能由于以下几个原因导致: 网络不稳定:频繁断开可能是由于网络不稳定导致的,可以尝试优化网络连接。 心跳机制问题&…...
网络安全内容整理二
网络嗅探技术 网络监听 网络监听,也称网络嗅探(Network Sniffing):在他方未察觉的情况下捕获其通信报文、通信内容的技术 网卡的工作模式: 1.广播模式(Broadcast Mode):网卡能够接收网络中的广播信息 2.组播模式(Multicast Mo…...
IDE解说
IDE(Integrated Development Environment,集成开发环境) 是一种集成了多种开发工具的软件应用程序,旨在简化软件开发过程。 IDE 通常包括代码编辑器、编译器或解释器、调试器、构建自动化工具和版本控制系统等组件。通过将这些工…...
安心护送转运平台小程序
安心护送转运平台小程序是一款基于FastAdminThinkPHPUniapp开发的非急救救护车租用转运平台小程序系统,可以根据运营者的业务提供类似短途接送救护服务,重症病人转运服务,长途跨省护送服务。...
mongodb文档字符串批量替换
【mongodb文档字符串批量替换脚本语句】 前言: 1、本方式对于数据量大的情况不适用,执行可能比较慢; 2、数据量大的情况,个人推荐代码层面解决,多线程替换更快: (1)写实体类的方式…...
模拟实现vector(非常详细)
模拟实现vector 1.基本概念2.vector()默认构造函数3.size()4.capacity()5.empty()6.reverse7.push_back()8.pop_back()9.operator[ ]10.resize()11.insert() 1.基本概念 上一节我们讲了vector的概念以及常用的接口,这一节我们讲一下它的实现,它的底层其实…...
证明直纹极小曲面是平面或者正螺旋面.
目录 证明直纹极小曲面是平面或者正螺旋面 证明直纹极小曲面是平面或者正螺旋面 证明:设极小直纹面 S S S的参数表示为 r ( u , v ) a ( u ) v c ( u ) . (u,v)\mathbf{a}(u)v\mathbf{c}(u). (u,v)a(u)vc(u).则 r u a ′ v c ′ , r v c , r u ∧ r v a ′ ∧…...
电子应用设计方案-34:智能镜子系统方案设计
智能镜子系统方案设计 一、引言 智能镜子作为一种新兴的智能设备,将传统镜子与现代科技相结合,为用户提供了丰富的信息展示和交互功能。它不仅可以作为普通镜子使用,还能够显示天气、新闻、日程安排等信息,甚至可以与智能家居设备…...
前端项目从开发到部署全流程介绍
一、项目初始化 创建项目目录 首先创建一个新的项目目录,例如my - front - end - project。使用命令mkdir my - front - end - project && cd my - front - end - project。 初始化项目 使用npm init或yarn init来初始化项目,这会生成一个packag…...
Vue3.0组件之间通信(defineProps 和 defineEmits 及 defineExpose)
前言: 一、父传子 defineProps二、子传父 defineEmits三、子组件暴露属性和方法给父组件 defineExpose四、依赖注入Provide / Inject 在 <script setup> 中必须使用 defineProps 和 defineEmits API 来声明 props 和 emits ,它们具备完整的类型推…...
多种平台上安装部署调试Open5GS(四)
OpenWRT 源码安装 UERANSIM 安装依赖openwrt源码安装cmake其他依赖准备UERANSIM安装测试验证Open5GS 是一个功能完善的开源5G项目,具备5G、4G核心网功能,最新代码支持R17标准, 本系列文章介绍Open5GS在x86、ARM平台上的安装部署方法,并通过搭建UERANSIN、商用5G基站和终端两…...
KST-3D01型胎儿超声仿真体模、吸声材料以及超声骨密度仪用定量试件介绍
一、KST-3D01型胎儿超声仿真体模 KST—3D01型胎儿超声体模,采用仿羊水环境中内置胎龄为7个月大仿胎儿设计。用于超声影像系统3D扫描演示装置表面轮廓呈现和3D重建。仿羊水超声影像呈暗回声(无回波)特性,仿胎儿超声影像呈对比明显…...
论文笔记-WWW2024-ClickPrompt
论文笔记-WWW2024-ClickPrompt: CTR Models are Strong Prompt Generators for Adapting Language Models to CTR Prediction ClickPrompt: CTR模型是大模型适配CTR预测任务的强大提示生成器摘要1.引言2.预备知识2.1传统CTR预测2.2基于PLM的CTR预测 3.方法3.1概述3.2模态转换3.…...
VTK中对于相机camera的设置
1. 相机的核心属性 在 VTK 中,vtkCamera 的核心属性有默认值。如果你不设置这些属性,相机会使用默认值来渲染场景。 Position(默认值:(0, 0, 1)): 默认情况下,相机位于 Z 轴正方向的 (0, 0, 1)…...
小程序解决大问题-物流系统磁盘爆满问题处理
晚上七点,煤矿调运的物流调度系统突然磁盘报名导致服务崩溃。系统用的是微服务,没有详细操作说明,也不敢动,运煤车辆排起了长队,只能联系厂家处理。好在经过30多分钟的处理,服务终于启动,系统运…...
OGRE 3D----5. OGRE和QML事件交互
在现代图形应用程序开发中,OGRE(Object-Oriented Graphics Rendering Engine)作为一个高性能的3D渲染引擎,广泛应用于游戏开发、虚拟现实和仿真等领域。而QML(Qt Modeling Language)则是Qt框架中的一种声明式语言,专注于设计用户界面。将OGRE与QML结合,可以充分利用OGR…...
docker搭建nginx
一. 直接启动nginx镜像 1. 下载nginx镜像 docker pull nginx 2. 运行镜像 docker run -p 8080:80 --name web -d nginx 3. 网址查看 xx.xx.xx.xx:8080 二. 挂在文件启动nginx镜像 1. 拷贝docker文件到本地 docker cp web:/etc/nginx/nginx.conf /root/data/config/nginx…...
Qt之样式表设置总结。。。持续更新
参考文章链接如下: Qt样式表之一:Qt样式表和盒子模型介绍 Qt样式表之二:QSS语法及常用样式 Qt样式表之三:实现按钮三态效果的三种方法 Qt样式表之一:QSS名词解释 Qt样式表之二:常用控件qss Qt样式表之三:QSS奇技淫巧 样式表介绍 Qt样式表是一个可以自定义部件外观的十…...
若依项目源码阅读
源码阅读 前端代码分析 代码生成器生成的前端代码有两个,分别是course.js用于向后端发送ajax请求的接口代码,另一个是index.vue,用于在浏览器展示课程管理的视图组件。前端的代码是基于vue3elementplus。 template用于展示前端组件别的标签…...
Ubuntu20.04运行R-VIO2
目录 1.环境配置2.构建项目3. 运行 VIO 模式4.结果图 1.环境配置 CMakeLists.txt中 C 使用 14、opencv使用4 2.构建项目 克隆代码库: 在终端中执行以下命令克隆项目:git clone https://github.com/rpng/R-VIO2.git编译项目: 使用 catkin_m…...
【Python运维】容器管理新手入门:使用Python的docker-py库实现Docker容器管理与监控
《Python OpenCV从菜鸟到高手》带你进入图像处理与计算机视觉的大门! 解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 随着容器技术的广泛应用,Docker已经成为开发和运维中的标准工具之一。使用Python语言管理Docker容器,不仅可以自动化繁琐的容器操作,还能…...
SQL基础入门——SQL基础语法
1. 数据库、表、列的创建与管理 在SQL中,数据库是一个数据的集合,包含了多个表、视图、索引、存储过程等对象。每个表由若干列(字段)组成,表中的数据行代表记录。管理数据库和表的结构是SQL的基础操作。 1.1 创建数据…...
Lumos学习王佩丰Excel第十八讲:LOOKUP函数与数组
一、回顾统计函数 1、使用SUMIF函数 sumif(条件区域,求和条件,求和区域) 2、使用SUMIFS函数 SUMIFS(求和范围, 条件范围1, 条件1, 条件范围2, 条件2, ...) 二、认识数组 1、数组生成原理 所谓数组,是有序的元素序列。组成数组的各个变量称为数组的元素。对于Ex…...
第二节——计算机网络(四)物理层
车载以太网采用差分双绞线车载以太网并未指定特定的连接器,连接方式更为灵活小巧,能够大大减轻线束重量。传统以太网一般使用RJ45连接器连接。车载以太网物理层需满足车载环境下更为严格的EMC要求,100BASE-T1\1000BASE-T1对于非屏蔽双绞线的传…...
【接口封装】——11、Qt 的单例模式
宏定义: Q_GLOBAL_STATIC(NotifyManager,theInstance) 函数定义: class NotifyManager : public QObject {Q_OBJECTpublic:NotifyManager(QObject *parent nullptr);~NotifyManager();static NotifyManager*getInstance(); //单例模式 } 源代码&#…...
理解字母形状,从而获得含义
英文字母,都是象形符号,所以,理解其形象,所象之形,是一项重要的工作,和非常有意义事情。也是我们快速记住大量单词,将单词从底层逻辑开始理清,融会贯通扩展记忆容量的重要办法之一。…...
redis揭秘-redis01-redis单例与集群安装总结
文章目录 【README】【1】安装单机【1.1】安装环境【1.2】安装步骤 【2】redis集群主从模式配置【2.1】集群架构【2.2】redis集群主从模式搭建步骤【2.3】redis集群主从模式的问题(单点故障问题) 【3】redis集群哨兵模式配置【3.1】集群架构【3.2】redis…...
mini-spring源码分析
IOC模块 关键解释 beanFactory:beanFactory是一个hashMap, key为beanName, Value为 beanDefination beanDefination: BeanDefinitionRegistry,BeanDefinition注册表接口,定义注册BeanDefinition的方法 beanReference:增加Bean…...
RVO动态避障技术方案介绍
原文:RVO动态避障技术方案介绍 - 哔哩哔哩 我们在开发游戏的时候经常会遇到这样的问题,当我们寻路的时候,其它人也在寻路,如何避免不从其它人的位置穿过。这个叫做动态避障,目前主流的解决方案就是RVO。本节我们来介绍…...
HTML CSS JS基础考试题与答案
一、选择题(2分/题) 1.下面标签中,用来显示段落的标签是( d )。 A、<h1> B、<br /> C、<img /> D、<p> 2. 网页中的图片文件位于html文件的下一级文件夹img中,…...
【C语言】二叉树(BinaryTree)的创建、3种递归遍历、3种非递归遍历、结点度的实现
代码主要实现了以下功能: 二叉树相关数据结构定义 定义了二叉树节点结构体 BiTNode,包含节点数据值(字符类型)以及指向左右子树的指针。 定义了顺序栈结构体 SqStack,用于存储二叉树节点指针,实现非递归遍历…...
MySQL Workbench 数据库建模详解:从设计到实践
目录 数据库建模基础概念MySQL Workbench 简介与安装 什么是 MySQL Workbench?安装与环境配置 MySQL Workbench 数据库建模功能详解 EER 图(实体关系图)数据库反向工程数据库正向工程模型同步与版本管理 MySQL Workbench 数据库建模实战教程…...
【字体】Fire Code连字效果开启
Vscode 开启方法 1、设置字体Fire Code 放在最前面的即可: 2、启用连字 继续往下找到“在 settings.json 中编辑”,然后设置"editor.fontLigatures": true : 保存即可。 Sublime 开启方法 设置中设置字体后,启…...
springboot kafka在kafka server AUTH变动后consumer自动销毁
前言 笔者使用了kafka用来传输数据,笔者在今年10月写了文章,怎么使用配置化实现kafka的装载:springboot kafka多数据源,通过配置动态加载发送者和消费者-CSDN博客 不过在实际运行中,kafka broker是加密的,…...
第六届国际科技创新(IAECST 2024)暨第四届物流系统与交通运输(LSTT 2024)
重要信息 会议官网:www.lstt.org 大会时间:2024年12月6-8日 大会地点:中国-广州 简介 第六届国际科技创新暨第四届物流系统与交通运输国际(LSTT 2024)将于2024年12月6-8日在广州举办,这是一个集中探讨…...
【Vue3】【Naive UI】< a >标签
【Vue3】【Naive UI】< a >标签 超链接及相关属性其他属性 【VUE3】【Naive UI】<NCard> 标签 【VUE3】【Naive UI】<n-button> 标签 【VUE3】【Naive UI】<a> 标签 <a> 标签HTML中的一个锚&…...
Fortran mpi在Linux的安装
最近编译一个程序需要需要 Fortran mpi 编译器,则需要安装 Fortran编辑器和MPI库,以下是具体的安装步骤: 一、安装 Fortran 编译器(gfortran) 在conda环境中安装: conda install -c conda-forge gfortra…...
蓝桥-希尔排序模板题
第一眼看到这个题还在想希尔排序模板不记得了,于是去网上了搜了一个,但是考虑到这种题只看测试点能不能通过,于是用Arrays方法试了一下,发现也可以。 1.希尔排序模板ac代码 package yunkePra;import java.util.Scanner;public cl…...
深入学习指针(5)!!!!!!!!!!!!!!!
文章目录 1.回调函数是什么?2.qsort使用举例2.1使用qsort函数排序整形数据2.2使用sqort排序结构数据 3.qsort函数的模拟实现 1.回调函数是什么? 回调函数就是⼀个通过函数指针调⽤的函数。 如果你把函数的指针(地址)作为参数传递…...
windows 应用 UI 自动化实战
UI 自动化技术架构选型 UI 自动化是软件测试过程中的重要一环,网络上也有很多 UI 自动化相关的知识或资料,具体到 windows 端的 UI 自动化,我们需要从以下几个方面考虑: 开发语言 毋庸置疑,在 UI 自动化测试领域&am…...
nodejs相关知识介绍
1、nodejs官方文档: https://nodejs.org/zh-cn nodejs可以用nvm进入安装; 2、npm说明: npm官方教程:https://npm.p2hp.com/ npm是 Node.js 的标准包管理器,也就是说nodejs安装好,npm也就安装好了&#…...
How to monitor Spring Boot apps with the AppDynamics Java Agent
本文介绍如何使用 AppDynamics Java 代理监视 Azure Spring Apps 中的 Spring Boot 应用程序。 使用 AppDynamics Java 代理可以: 监视应用程序使用环境变量配置 AppDynamics Java 代理 在 AppDynamics 仪表板中检查所有监视数据 How to monitor Spring Boot app…...
安装SQL Server 2022提示需要Microsoft .NET Framework 4.7.2 或更高版本
安装SQL Server 2022提示需要Microsoft .NET Framework 4.7.2 或更高版本。 原因是:当前操作系统版本为Windows Server 2016 Standard版本,其自带的Microsoft .NET Framework 版本为4.6太低,不满足要求。 根据报错的提示,点击链接…...
TypeScript核心语法(5)——函数
简介 函数的类型声明,需要在声明函数时,给出参数的类型和返回值的类型。 function hello(a: string): void {console.log("hello " txt); } 上面示例中,函数hello()在声明时,需要给出参数a的类型(stri…...
【MyBatis】验证多级缓存及 Cache Aside 模式的应用
文章目录 前言1. 多级缓存的概念1.1 CPU 多级缓存1.2 MyBatis 多级缓存 2. MyBatis 本地缓存3. MyBatis 全局缓存3.1 MyBatis 全局缓存过期算法3.2 CacheAside 模式 后记MyBatis 提供了缓存切口, 采用 Redis 会引入什么问题?万一遇到需强一致场景&#x…...