自由学习记录(28)

news2025/2/25 11:20:40

C# 中的流(Stream

流(Stream)是用于读取和写入数据的抽象基类

流表示从数据源读取或向数据源写入数据的矢量过程。

C# 中的流类是从 System.IO.Stream 基类派生的,提供了多种具体实现,每种实现都针对不同的数据源或用途。下面是一些常见的流类型及其作用:

流类型一般都被整合成了一个对象既管输入流 也管输出流,基础概念中的Stream也是如此,只不过有输入输出两个细分的类概念而已

1. 流的基础概念

  • 流(Stream):在计算机中表示一种数据的连续流动,可以是从文件、内存、网络或其他设备中读取数据,或者将数据写入这些设备。
  • 输入流(InputStream):用于从数据源读取数据。
  • 输出流(OutputStream):用于将数据写入到数据源。

2. 常见的流类型

  • FileStream:用于从文件读取或向文件写入数据。
  • MemoryStream:用于在内存中读写数据,适用于不需要持久化的临时数据处理
  • NetworkStream:用于网络通信,处理通过网络传输的数据。
  • BufferedStream:为其他流提供缓冲,以提高读取和写入性能。
  • StreamReaderStreamWriter:用于处理文本数据的读写操作,通常与其他流(如 FileStream)一起使用。
  • CryptoStream:用于加密和解密数据流。
  • GZipStreamDeflateStream:用于压缩和解压缩数据流。

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.JsonXmlSerializer

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.JsonXmlSerializer 更加安全和现代。

特性(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) ,元编程机制,向代码元素(如类、方法、属性等)附加元数据。

这种元数据可以在运行时通过反射读取,并驱动额外的逻辑行为


特性的原理

  1. 特性是类的实例

    • 特性本质上是从 System.Attribute 派生的类

  2. 特性的声明方式

    • 特性类必须继承自 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] 特性可以在方法调用前校验参数。

总结:特性的工作流程

  1. 声明特性:通过继承 System.Attribute 定义自定义特性。
  2. 应用特性:将特性以 [AttributeName] 的形式附加到代码元素上。
  3. 元数据存储:编译器将特性信息存储在程序集的元数据中。
  4. 读取特性:运行时通过反射获取元数据,执行逻辑。

特性看似只是加了个 [],实际上背后依赖了 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 替代字符(通常是 )。
  • 索引和长度合法性
    • indexcount 必须满足:
      • 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);
  1. byte[] array:写入文件的数据

  2. int offset:写入数据的起始索引( array[offset] 开始写入)

  3. 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 方法,用于操作任意二进制数据。它的三个参数控制了写入的范围和数据来源,以下是设计理念:

  1. 灵活性offsetcount 允许你仅写入字节数组的一部分,而不是整个数组。
  2. 效率:你可以通过精确控制写入范围来优化性能,避免不必要的字节拷贝。
  3. 防止错误:如果默认写入整个数组,可能导致意外写入多余数据。

如何简化操作?

大多数常见的用法可以显式写成:fs.Write(data, 0, data.Length);

使用 BinaryWriter

BinaryWriter 是一个更高层的封装,简化了写入数据的操作,无需明确指定 offsetcount。它会直接将完整的字节数组写入文件:

using (var fs = new FileStream("example.txt", FileMode.Create, FileAccess.Write))
using (var writer = new BinaryWriter(fs))
{
    byte[] data = new byte[] { 65, 66, 67 }; // ABC
    writer.Write(data); // 自动写入整个数组
}
使用 StreamWriter(适用于文本数据)

如果处理的是文本而不是二进制数据,StreamWriter 更适合,它完全隐藏了底层字节操作:

using (var writer = new StreamWriter("example.txt"))
{
    writer.Write("Hello, World!"); // 写入文本
}
byte[] array
  • 文件流操作是以字节为单位,需要将任何数据(如文本、数字、图像)转换为字节数组。
  • 常见的转换方法:
    • 字符串 转换为字节数组Encoding.UTF8.GetBytes(string)
    • 数值类型 转换为字节数组:BitConverter.GetBytes(int)
offsetcount
  • 通过 offsetcount 参数可以选择性地从字节数组中提取一部分数据写入文件。
  • 示例:
    byte[] data = { 65, 66, 67, 68, 69 }; // A, B, C, D, E
    fs.Write(data, 2, 2); // 从索引 2 开始写入 2 个字节 -> 写入 "CD"
    
性能优化
  • 数据量较大,使用 fs.Write() 尽量批量写入而不是逐字节写入
  • 能减少 I/O 操作次数,提升性能

常见错误

  1. 数组越界

    • 如果 offset + count > array.Length,会抛出 ArgumentException
    • 在使用前检查数组长度以避免错误:
      if (offset + count > data.Length)
          throw new ArgumentException("指定的范围超出了数组长度!");
      
  2. 流未打开或已关闭

    • 如果文件流在调用 Write() 时已关闭,ObjectDisposedException 会被抛出
  3. 权限不足

    • 如果文件流是只读模式(FileAccess.Read,会抛出 NotSupportedException

移动会把文件夹里的所有东西一起移动过去

File.ReadAllLines()

File.ReadAllText()

File.Delete()

File.Copy()

File.Replace()

 Application.dataPath

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

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

相关文章

Redis3——线程模型与数据结构

Redis3——线程模型与数据结构 本文讲述了redis的单线程模型和IO多线程工作原理&#xff0c;以及几个主要数据结构的实现。 1. Redis的单线程模型 redis6.0之前&#xff0c;一个redis进程只有一个io线程&#xff0c;通过reactor模式可以连接大量客户端&#xff1b;redis6.0为了…

使用playwright自动化测试时,npx playwright test --ui打开图形化界面时报错

使用playwright自动化测试时&#xff0c;npx playwright test --ui打开图形化界面时报错 1、错误描述&#xff1a;2、解决办法3、注意符号的转义 1、错误描述&#xff1a; 在运行playwright的自动化测试项目时&#xff0c;使用npm run test无头模式运行正常&#xff0c;但使用…

深度学习模型:门控循环单元(GRU)详解

本文深入探讨了门控循环单元&#xff08;GRU&#xff09;&#xff0c;它是一种简化版的长短期记忆网络&#xff08;LSTM&#xff09;&#xff0c;在处理序列数据方面表现出色。文章详细介绍了 GRU 的基本原理、与 LSTM 的对比、在不同领域的应用以及相关的代码实现&#xff0c;…

用html+jq实现元素的拖动效果——js基础积累

用htmljq实现元素的拖动效果 效果图如下&#xff1a; 将【item10】拖动到【item1】前面 直接上代码&#xff1a; html部分 <ul id"sortableList"><li id"item1" class"w1" draggable"true">Item 1</li><li …

单片机学习笔记 12. 定时/计数器_定时

更多单片机学习笔记&#xff1a;单片机学习笔记 1. 点亮一个LED灯单片机学习笔记 2. LED灯闪烁单片机学习笔记 3. LED灯流水灯单片机学习笔记 4. 蜂鸣器滴~滴~滴~单片机学习笔记 5. 数码管静态显示单片机学习笔记 6. 数码管动态显示单片机学习笔记 7. 独立键盘单片机学习笔记 8…

【乐企文件生成工程】搭建docker环境,使用docker部署工程

1、自行下载docker 2、自行下载docker-compose 3、编写Dockerfile文件 # 使用官方的 OpenJDK 8 镜像 FROM openjdk:8-jdk-alpine# 设置工作目录 WORKDIR ./app# 复制 JAR 文件到容器 COPY ../lq-invoice/target/lq-invoice.jar app.jar # 暴露应用程序监听的端口 EXPOSE 1001…

React基础知识三 router路由全指南

现在最新版本是Router6和Router5有比较大的变化&#xff0c;Router5和Router4变化不大&#xff0c;本文以Router6的写法为主&#xff0c;也会对比和Router5的不同。比较全面。 安装路由 npm i react-router-dom基本使用 有两种Router&#xff0c;BrowserRouter和HashRouter&…

【C#】书籍信息的添加、修改、查询、删除

文章目录 一、简介二、程序功能2.1 Book类属性&#xff1a;方法&#xff1a; 2.2 Program 类 三、方法&#xff1a;四、用户界面流程&#xff1a;五、程序代码六、运行效果 一、简介 简单的C#控制台应用程序&#xff0c;用于管理书籍信息。这个程序将允许用户添加、编辑、查看…

打造去中心化交易平台:公链交易所开发全解析

公链交易所&#xff08;Public Blockchain Exchange&#xff09;是指基于公有链&#xff08;如以太坊、波场、币安智能链等&#xff09;建立的去中心化交易平台。与传统的中心化交易所&#xff08;CEX&#xff09;不同&#xff0c;公链交易所基于区块链技术实现资产交换的去中心…

CLIP模型也能处理点云信息

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢&#xff0c;在这里我会分享我的知识和经验。&am…

关于NXP开源的MCU_boot的项目心得

MCU的启动流程细查 注意MCU上电第一个函数运行的就是Reset_Handler函数&#xff0c;下图是表示了这个函数做了啥事情&#xff0c;注意加强一下对RAM空间的段的印象&#xff0c;从上到下是栈&#xff0c;堆&#xff0c;.bss段&#xff0c;.data段。 bootloader的难点 固件完…

MySQL5.6升级MySQL5.7

升级方式介绍 08 数据库服务版本升级方法 5.6 – 5.7 – 8.0 数据库版本升级方法&#xff1a; Inplace-本地升级 步骤一&#xff1a;在同一台服务器中&#xff0c;需要部署高版本数据库服务实例步骤二&#xff1a;低版本数据库中的数据进行备份迁移&#xff0c;迁移到高版本…

怎么理解BeamSearch?

在大模型推理中&#xff0c;常会用到BeamSearch&#xff0c;本文就BeamSearch原理与应用理解展开讲解。 一、BeamSearch原理 Beam Search 是一种启发式搜索算法&#xff0c;常用于自然语言处理&#xff08;NLP&#xff09;和其他需要生成序列的任务中&#xff0c;比如机器翻译…

shodan2-批量查找CVE-2019-0708漏洞

声明&#xff01; 学习视频来自B站up主 泷羽sec 有兴趣的师傅可以关注一下&#xff0c;如涉及侵权马上删除文章&#xff0c;笔记只是方便各位师傅的学习和探讨&#xff0c;文章所提到的网站以及内容&#xff0c;只做学习交流&#xff0c;其他均与本人以及泷羽sec团队无关&#…

SciPy Optimize和 CVXPY对比

CVXPY和SciPy Optimize模块都是在Python中解决优化问题的强大工具&#xff0c;但它们是为不同类型的问题而设计的&#xff0c;具有不同的优点和局限性。本文对比两者的优缺点&#xff0c;阐述各自的应用场景&#xff0c;同时解释常用求解器&#xff0c;并给出实际示例进行说明。…

DevOps工程技术价值流:GitLab源码管理与提交流水线实践

在当今快速迭代的软件开发环境中&#xff0c;DevOps&#xff08;开发运维一体化&#xff09;已经成为提升软件交付效率和质量的关键。而GitLab&#xff0c;作为一个全面的开源DevOps平台&#xff0c;不仅提供了强大的版本控制功能&#xff0c;还集成了持续集成/持续交付(CI/CD)…

Android Studio 右侧工具栏 Gradle 不显示 Task 列表

问题&#xff1a; android studio 4.2.1版本更新以后AS右侧工具栏Gradle Task列表不显示&#xff0c;这里需要手动去设置 解决办法&#xff1a; android studio 2024.2.1 Patch 2版本以前的版本设置&#xff1a;依次打开 File -> Settings -> Experimental 选项&#x…

Linux详解:文件权限

文章目录 前言Linux文件权限基础文件成员与三组权限字符 权限的修改修改文件所有者总结 前言 在浩瀚的操作系统世界中&#xff0c;Linux以其开源、灵活和强大的特性&#xff0c;成为了服务器、开发环境以及众多个人用户的首选。而在Linux的众多特性中&#xff0c;文件权限机制…

SeggisV1.0 遥感影像分割软件【源代码】讲解

在此基础上进行二次开发&#xff0c;开发自己的软件&#xff0c;例如&#xff1a;【1】无人机及个人私有影像识别【2】离线使用【3】变化监测模型集成【4】个人私有分割模型集成等等&#xff0c;不管是您用来个人学习还是公司研发需求&#xff0c;都相当合适&#xff0c;包您满…

Spark常问面试题---项目总结

一、数据清洗&#xff0c;你都清洗什么&#xff1f;或者说 ETL 你是怎么做的&#xff1f; 我在这个项目主要清洗的式日志数据&#xff0c;日志数据传过来的json格式 去除掉无用的字段&#xff0c;过滤掉json格式不正确的脏数据 过滤清洗掉日志中缺少关键字段的数据&#xff…