C# 中的 Stream

news2025/1/16 21:19:39

一、揭开 Stream 的神秘面纱

在 C# 的编程世界里,Stream 如同一条隐藏在程序深处的神秘河流,默默地承载着数据的流动。当我们读取文件中的文字、接收网络传来的信息,或是在内存中处理数据块时,Stream 都在幕后发挥着关键作用,它就像是连接数据源头与目的地的无形管道,确保数据的有序传输。

Stream 是一种表示基于流的输入输出的抽象基类,它为 C# 中所有流相关操作提供了基础框架。在这个框架下,无论是文件、内存中的数据块,还是网络数据,都能以连续的方式被读取或写入。这就好比我们通过水管输水,水在水管中持续流动,而 Stream 对于数据来说,就是那根保证数据平稳、持续流动的 “水管”。

二、Stream 的基本概念

(一)Stream 是什么

在 C# 的庞大类库体系中,Stream 是一个抽象基类,它为基于流的输入输出操作构建了一个通用模型。这意味着它定义了一系列的方法和属性,为读取、写入和管理数据流提供了基本框架,但不能被直接实例化 。就像建筑师设计了一座建筑的蓝图,而具体的建筑(如 FileStream、MemoryStream、NetworkStream 等子类)需要依据这张蓝图来构建。

这些子类继承了 Stream 的特性,并针对不同的数据来源和目标进行了具体化实现。例如,FileStream 专门用于文件的读写操作,它能够直接与磁盘上的文件进行交互,将文件视为字节流进行处理;MemoryStream 则专注于内存中的数据操作,允许在内存中创建和操作数据流,适用于临时存储和处理数据的场景;NetworkStream 用于网络数据的传输,在客户端和服务器之间建立起数据传输的通道。

(二)Stream 的主要特点

Stream 的显著特点之一是顺序性。数据在 Stream 中如同水流一般,按照先后顺序依次流动,我们只能按照这种顺序对数据进行读取和写入操作,无法像在数组中那样随机访问数据。这一特性保证了数据处理的有序性,特别适用于处理大量连续的数据。

Stream 的连续性也非常重要。它使得数据可以以连续的方式进行处理,而不需要一次性将所有数据加载到内存中。在处理大文件时,我们可以通过 Stream 逐块读取数据,而不是将整个大文件全部读入内存,这样极大地减少了内存的占用,提高了程序的性能和稳定性。这种连续性还体现在数据的写入过程中,数据能够持续地写入到目标位置,保证数据的完整性。

三、Stream 的常见操作

(一)打开流

在 C# 中,打开流的方式因流的类型而异 。以最常用的文件流 FileStream 为例,我们通过其构造函数来指定文件路径、打开模式以及访问权限等参数。

当我们想要读取一个已存在的文件时,可以这样写:

using System.IO;
FileStream fileStreamRead = new FileStream("example.txt", FileMode.Open, FileAccess.Read);

这段代码中,“example.txt” 是文件的路径,FileMode.Open 表示以打开现有文件的模式进行操作,如果文件不存在则会抛出异常;FileAccess.Read 指定了我们对该文件只有读取的权限。

若要创建一个新文件并准备写入数据,代码如下:

FileStream fileStreamWrite = new FileStream("newFile.txt", FileMode.Create, FileAccess.Write);

这里 FileMode.Create 表示如果文件不存在则创建新文件,如果文件已存在则覆盖原有内容;FileAccess.Write 赋予了对文件的写入权限。

对于内存流 MemoryStream,由于它是在内存中操作数据流,不需要指定外部文件路径,直接实例化即可:

MemoryStream memoryStream = new MemoryStream();

这种方式创建的内存流初始为空,可以随时向其中写入数据或从中读取数据。

(二)读取数据

从流中读取数据是 Stream 的核心操作之一,以 FileStream 读取文件内容为例,我们可以使用 Read 方法来实现。该方法会将流中的数据读取到一个字节数组中,并返回实际读取的字节数。

using System.IO;
using (FileStream fileStream = new FileStream("example.txt", FileMode.Open, FileAccess.Read))
{
    byte[] buffer = new byte[1024];
    int bytesRead;
    while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) > 0)
    {
        string content = System.Text.Encoding.UTF8.GetString(buffer, 0, bytesRead);
        Console.Write(content);
    }
}

在这段代码中,我们首先创建了一个大小为 1024 字节的缓冲区 buffer ,用于存储从文件流中读取的数据。在 while 循环中,每次调用 Read 方法尝试从文件流中读取最多 1024 字节的数据到 buffer 中,返回的 bytesRead 表示实际读取到的字节数。当 bytesRead 为 0 时,表示已经到达文件末尾,循环结束。每次读取到数据后,我们使用 UTF - 8 编码将字节数组转换为字符串并输出到控制台。

(三)写入数据

将数据写入流同样通过 Stream 的 Write 方法来实现。以向文件中写入数据为例,以下是使用 FileStream 和 StreamWriter 的示例代码:

using System.IO;
string contentToWrite = "Hello, Stream!";
using (FileStream fileStream = new FileStream("output.txt", FileMode.Create, FileAccess.Write))
using (StreamWriter streamWriter = new StreamWriter(fileStream))
{
    streamWriter.Write(contentToWrite);
}

在这段代码中,我们首先创建了一个 FileStream 对象,以创建模式打开名为 “output.txt” 的文件,并赋予写入权限。然后,我们创建了一个 StreamWriter 对象,将其与 FileStream 对象关联起来。最后,通过 StreamWriter 的 Write 方法将字符串 “Hello, Stream!” 写入到文件中。在使用完 StreamWriter 和 FileStream 后,由于我们使用了 using 语句,它们会自动被正确关闭和释放资源。

(四)关闭流

关闭流是非常重要的操作,它能确保资源的正确释放,避免资源泄漏和潜在的错误。在 C# 中,我们强烈推荐使用 using 语句来管理流对象的生命周期。

using System.IO;
using (FileStream fileStream = new FileStream("example.txt", FileMode.Open, FileAccess.Read))
{
    // 在这里进行文件读取操作
    byte[] buffer = new byte[1024];
    int bytesRead = fileStream.Read(buffer, 0, buffer.Length);
}
// 当离开using语句块时,fileStream会自动调用Dispose方法关闭流

在上述代码中,当程序执行到 using 语句块结束时,无论在块内是否发生异常,文件流 fileStream 都会自动调用其 Dispose 方法,从而关闭流并释放与之关联的所有资源。如果不使用 using 语句,我们则需要手动调用 Close 方法或 Dispose 方法来关闭流,例如:

FileStream fileStream = new FileStream("example.txt", FileMode.Open, FileAccess.Read);
try
{
    byte[] buffer = new byte[1024];
    int bytesRead = fileStream.Read(buffer, 0, buffer.Length);
}
finally
{
    fileStream.Close();
}

在这个示例中,我们在 try - finally 块中进行文件读取操作,并在 finally 块中调用 Close 方法关闭文件流。这样可以确保无论读取过程中是否发生异常,文件流都能被正确关闭。但相比之下,using 语句的方式更加简洁明了,且能有效避免因代码逻辑复杂而遗漏关闭流的情况。

四、Stream 的常用类型

(一)FileStream

FileStream 就像是连接程序与磁盘文件的桥梁,专门用于文件的读写操作。它允许我们以字节为单位,对文件进行随机访问和顺序访问。在处理大文件时,FileStream 的优势尤为明显,它可以通过设置缓冲区大小,减少磁盘 I/O 操作的次数,从而提高读写效率。例如,当我们需要读取一个大型的视频文件时,使用 FileStream 能够逐块读取数据,避免一次性将整个大文件加载到内存中,有效降低内存占用。

在构造 FileStream 对象时,我们需要指定文件路径、打开模式、访问权限等参数。以读取文件为例,代码如下:

using System.IO;
FileStream fileStream = new FileStream("example.txt", FileMode.Open, FileAccess.Read);

这段代码中,“example.txt” 是要读取的文件路径,FileMode.Open 表示以打开现有文件的模式进行操作,FileAccess.Read 则指定了对该文件的读取权限。通过这种方式,我们就可以使用 FileStream 对象对文件进行后续的读取操作。

(二)MemoryStream

MemoryStream 如同一个在内存中开辟的临时数据存储空间,主要用于在内存中处理数据流。与 FileStream 不同,它不需要与外部文件进行交互,数据的读写都在内存中完成。这使得 MemoryStream 在处理一些临时数据或需要频繁进行数据操作的场景中表现出色。例如,在进行数据加密和解密的过程中,我们可以将待处理的数据先存储在 MemoryStream 中,方便进行加密算法的运算,而无需频繁地读写磁盘文件,大大提高了处理速度。

使用 MemoryStream 非常方便,以下是一个简单的示例,展示了如何在 MemoryStream 中写入和读取数据:

using System.IO;
using System.Text;
MemoryStream memoryStream = new MemoryStream();
string data = "Hello, MemoryStream!";
byte[] buffer = Encoding.UTF8.GetBytes(data);
memoryStream.Write(buffer, 0, buffer.Length);
memoryStream.Position = 0;
byte[] readBuffer = new byte[buffer.Length];
int bytesRead = memoryStream.Read(readBuffer, 0, readBuffer.Length);
string result = Encoding.UTF8.GetString(readBuffer, 0, bytesRead);
Console.WriteLine(result);

在这段代码中,我们首先创建了一个 MemoryStream 对象。然后,将字符串数据转换为字节数组,并写入到 MemoryStream 中。通过设置 Position 属性为 0,将流的位置重置到起始位置,以便进行后续的读取操作。最后,从 MemoryStream 中读取数据,并将其转换回字符串进行输出。

(三)BufferedStream

BufferedStream 为数据的读写提供了缓冲机制,它就像是在数据传输的路径上设置了一个临时仓库。当我们从流中读取数据时,BufferedStream 会一次性从底层流中读取多个字节的数据,并存储在缓冲区中。当我们再次读取数据时,如果缓冲区中有数据,就直接从缓冲区中读取,而不需要频繁地访问底层数据源,从而提高了读取效率。同样,在写入数据时,BufferedStream 会先将数据写入缓冲区,当缓冲区满了或者调用 Flush 方法时,才会将缓冲区中的数据一次性写入到底层流中,减少了对底层设备的写入次数。

下面是一个使用 BufferedStream 提高文件读取效率的示例:

using System.IO;
using (FileStream fileStream = new FileStream("example.txt", FileMode.Open, FileAccess.Read))
using (BufferedStream bufferedStream = new BufferedStream(fileStream))
{
    byte[] buffer = new byte[1024];
    int bytesRead;
    while ((bytesRead = bufferedStream.Read(buffer, 0, buffer.Length)) > 0)
    {
        // 处理读取到的数据
    }
}

在这个例子中,我们首先创建了一个 FileStream 对象来打开文件,然后将 FileStream 对象传递给 BufferedStream 的构造函数,创建了一个 BufferedStream 对象。通过 BufferedStream 的 Read 方法读取数据时,实际上是从缓冲区中读取数据,而不是直接从文件中读取,从而提高了读取效率。

(四)NetworkStream

NetworkStream 在网络通信领域发挥着关键作用,它实现了在网络上进行数据传输的功能。在客户端和服务器之间建立网络连接后,NetworkStream 就成为了数据传输的通道。无论是在开发网络应用程序,如即时通讯软件、文件传输工具,还是进行网络服务的开发,NetworkStream 都不可或缺。例如,在一个简单的聊天程序中,客户端和服务器之间通过 NetworkStream 进行消息的发送和接收,确保聊天信息能够实时、准确地在双方之间传递。

在使用 NetworkStream 时,通常需要与 TcpClient、TcpListener 等类配合使用。以下是一个简单的客户端和服务器之间通过 NetworkStream 进行数据传输的示例:

服务器端代码
using System;
using System.IO;
using System.Net.Sockets;
using System.Text;
class Server
{
    static void Main()
    {
        TcpListener listener = new TcpListener(1234);
        listener.Start();
        Console.WriteLine("服务器启动,等待客户端连接...");
        TcpClient client = listener.AcceptTcpClient();
        Console.WriteLine("客户端已连接。");
        NetworkStream stream = client.GetStream();
        byte[] buffer = new byte[1024];
        int bytesRead;
        while ((bytesRead = stream.Read(buffer, 0, buffer.Length))!= 0)
        {
            string receivedData = Encoding.UTF8.GetString(buffer, 0, bytesRead);
            Console.WriteLine("收到客户端发送的数据: " + receivedData);
        }
        client.Close();
        listener.Stop();
        Console.WriteLine("服务器已关闭。");
    }
}
客户端代码
using System;
using System.IO;
using System.Net.Sockets;
using System.Text;
class Client
{
    static void Main()
    {
        TcpClient client = new TcpClient("localhost", 1234);
        Console.WriteLine("客户端启动,正在连接服务器...");
        NetworkStream stream = client.GetStream();
        string message = "Hello, Server!";
        byte[] data = Encoding.UTF8.GetBytes(message);
        stream.Write(data, 0, data.Length);
        Console.WriteLine("已发送消息: " + message);
        client.Close();
        Console.WriteLine("客户端已关闭。");
    }
}

在这个示例中,服务器端通过 TcpListener 监听指定端口,当有客户端连接时,获取与客户端的连接并创建 NetworkStream 对象,通过该对象读取客户端发送的数据。客户端则通过 TcpClient 连接到服务器,创建 NetworkStream 对象后,将数据写入到流中发送给服务器。通过这种方式,实现了客户端和服务器之间的数据传输。

五、Stream 的实际应用场景

(一)文件读写操作

在文件读取操作中,Stream 可谓是 “主力军”。当我们需要从硬盘上读取一个文本文件时,FileStream 配合 StreamReader 能轻松完成任务。例如,在读取一篇小说文档时,代码如下:

using System.IO;
using (FileStream fileStream = new FileStream("novel.txt", FileMode.Open, FileAccess.Read))
using (StreamReader streamReader = new StreamReader(fileStream))
{
    string content = streamReader.ReadToEnd();
    Console.WriteLine(content);
}

这段代码首先通过 FileStream 以只读模式打开名为 “novel.txt” 的文件,然后将 FileStream 传递给 StreamReader,利用 StreamReader 的 ReadToEnd 方法将整个文件内容读取为一个字符串并输出到控制台。

在文件写入操作中,Stream 同样表现出色。假设我们要记录系统运行过程中的日志信息,就可以使用 FileStream 和 StreamWriter 来实现。以下是一个简单的日志写入示例:

using System.IO;
string logMessage = "系统在[具体时间]发生了[具体事件]";
using (FileStream fileStream = new FileStream("log.txt", FileMode.Append, FileAccess.Write))
using (StreamWriter streamWriter = new StreamWriter(fileStream))
{
    streamWriter.WriteLine(logMessage);
}

在这个例子中,FileStream 以追加模式打开 “log.txt” 文件,这样新的日志信息会被添加到文件末尾,而不会覆盖原有内容。StreamWriter 则负责将日志消息写入文件中。

在文件追加操作中,Stream 的优势也十分明显。比如我们在一个不断更新的文本文件中追加新的内容,以记录用户的操作记录。示例代码如下:

using System.IO;
string userAction = "用户[用户名]在[具体时间]进行了[具体操作]";
using (FileStream fileStream = new FileStream("userActions.txt", FileMode.Append, FileAccess.Write))
using (StreamWriter streamWriter = new StreamWriter(fileStream))
{
    streamWriter.WriteLine(userAction);
}

通过这种方式,每次用户进行操作时,对应的操作记录都会被追加到 “userActions.txt” 文件中,方便后续查看和分析。

(二)网络数据传输

在网络数据传输领域,Stream 是实现数据交换的关键桥梁。以常见的 HTTP 协议为例,当客户端向服务器发送请求时,请求数据会通过 NetworkStream 传输到服务器端;服务器处理完请求后,响应数据又通过 NetworkStream 返回给客户端。例如,在一个简单的网页爬虫程序中,我们需要从指定的网页获取数据,代码如下:

using System;
using System.IO;
using System.Net;
using System.Text;
class WebCrawler
{
    static void Main()
    {
        string url = "https://example.com";
        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
        HttpWebResponse response = (HttpWebResponse)request.GetResponse();
        using (Stream stream = response.GetResponseStream())
        using (StreamReader streamReader = new StreamReader(stream, Encoding.UTF8))
        {
            string htmlContent = streamReader.ReadToEnd();
            Console.WriteLine(htmlContent);
        }
        response.Close();
    }
}

在这段代码中,首先创建一个 HttpWebRequest 对象,用于向指定的 URL 发送请求。获取到响应后,通过 response.GetResponseStream () 方法获取到响应流,再使用 StreamReader 将流中的数据读取为字符串,从而得到网页的 HTML 内容。

在 FTP 协议中,Stream 同样发挥着重要作用。当我们需要从 FTP 服务器上传或下载文件时,就会用到 Stream。以下是一个简单的从 FTP 服务器下载文件的示例:

using System;
using System.IO;
using System.Net;
class FtpDownloader
{
    static void Main()
    {
        string ftpUrl = "ftp://ftp.example.com/file.txt";
        string username = "user";
        string password = "pass";
        FtpWebRequest request = (FtpWebRequest)WebRequest.Create(ftpUrl);
        request.Credentials = new NetworkCredential(username, password);
        request.Method = WebRequestMethods.Ftp.DownloadFile;
        using (FtpWebResponse response = (FtpWebResponse)request.GetResponse())
        using (Stream responseStream = response.GetResponseStream())
        using (FileStream fileStream = new FileStream("localFile.txt", FileMode.Create))
        {
            byte[] buffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = responseStream.Read(buffer, 0, buffer.Length)) > 0)
            {
                fileStream.Write(buffer, 0, bytesRead);
            }
        }
    }
}

在这个例子中,我们创建一个 FtpWebRequest 对象,设置好 FTP 服务器的地址、用户名、密码以及请求方法(下载文件)。获取到响应后,从响应中获取到流,再将流中的数据读取到本地文件中,完成文件的下载操作。

(三)内存数据处理

在内存数据处理方面,MemoryStream 是一个非常实用的工具。例如,在进行数据加密和解密的过程中,我们可以先将需要处理的数据存储在 MemoryStream 中,方便进行加密算法的运算。假设我们有一个简单的数据加密需求,将一段字符串进行加密处理后存储在内存中,代码如下:

using System.IO;
using System.Text;
class DataEncryption
{
    static void Main()
    {
        string originalData = "敏感信息";
        byte[] dataBytes = Encoding.UTF8.GetBytes(originalData);
        using (MemoryStream memoryStream = new MemoryStream())
        {
            memoryStream.Write(dataBytes, 0, dataBytes.Length);
            memoryStream.Position = 0;
            // 这里可以进行加密算法的操作,例如简单的异或加密
            byte[] encryptedData = new byte[dataBytes.Length];
            for (int i = 0; i < dataBytes.Length; i++)
            {
                encryptedData[i] = (byte)(dataBytes[i] ^ 0x1F);
            }
            memoryStream.Write(encryptedData, 0, encryptedData.Length);
            memoryStream.Position = 0;
            byte[] readData = new byte[memoryStream.Length];
            memoryStream.Read(readData, 0, readData.Length);
            string result = Encoding.UTF8.GetString(readData);
            Console.WriteLine(result);
        }
    }
}

在这段代码中,首先将原始字符串转换为字节数组,并写入到 MemoryStream 中。然后在内存流中对数据进行简单的异或加密操作,将加密后的数据再次写入内存流。最后从内存流中读取数据,并转换回字符串进行输出。

在数据转换场景中,MemoryStream 也能大显身手。比如将一个图像文件读取到内存中,进行格式转换后再进行存储或传输。以下是一个简单的将 Bitmap 图像转换为字节数组并存储在 MemoryStream 中的示例:

using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
class ImageConverter
{
    static void Main()
    {
        using (Bitmap bitmap = new Bitmap("image.jpg"))
        using (MemoryStream memoryStream = new MemoryStream())
        {
            bitmap.Save(memoryStream, ImageFormat.Png);
            byte[] imageBytes = memoryStream.ToArray();
            // 这里可以对imageBytes进行进一步的操作,如传输到网络等
        }
    }
}

在这个例子中,我们使用 Bitmap 类读取一个 JPEG 格式的图像文件,然后将其以 PNG 格式保存到 MemoryStream 中,最后通过 ToArray 方法将内存流中的数据转换为字节数组,方便后续的处理和传输。

六、总结与展望

通过对 C# 中 Stream 的深入探秘,我们像是揭开了数据处理领域的一层神秘面纱,领略到了它在数据传输与处理方面的强大魅力。从 Stream 的基本概念出发,了解到它作为抽象基类为各种数据输入输出操作提供了统一框架,再到深入学习其常见操作,包括打开、读取、写入和关闭流,以及熟悉 FileStream、MemoryStream、BufferedStream、NetworkStream 等常用类型及其在不同场景下的应用,我们逐步掌握了 Stream 这一强大工具的使用方法。

展望未来在实际编程中的应用,Stream 将为我们的开发工作带来诸多便利和效率提升。在文件处理方面,无论是日常的文本文件读写,还是处理大型二进制文件,Stream 都能以其高效的方式,确保数据的准确读写,为各类应用程序提供坚实的数据基础。在网络通信领域,随着互联网应用的不断发展,数据传输的需求日益增长,Stream 作为网络数据传输的核心,将在构建稳定、高效的网络连接和数据交互中发挥关键作用。在内存数据处理场景中,MemoryStream 等工具能够帮助我们更灵活地操作和管理内存中的数据,为数据的临时存储、加密解密、格式转换等操作提供便捷的解决方案。

总之,对 Stream 的深入理解和熟练运用,将使我们在 C# 编程的道路上如虎添翼,能够更加高效地开发出高质量、高性能的应用程序,以应对不断变化的编程需求和挑战。希望各位开发者能够在实际项目中积极运用 Stream,挖掘其更多的潜力,创造出更加优秀的软件作品 。

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

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

相关文章

nginx: [emerg] bind() to 0.0.0.0:80 failed 端口被占用

nginx: [emerg] bind() to 0.0.0.0:80 failed (10013: An attempt was made to access a socket in a way forbidden by its access permissions) 查看被占用的端口 被系统占用了 HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Services/HTTP 然后再进入nginx文件夹目录下…

《C++11》深入剖析正则表达式库:解锁文本处理的高效之道

在现代编程领域&#xff0c;文本处理是一项不可或缺的任务&#xff0c;而正则表达式无疑是这一领域的强大利器。C11标准库的引入&#xff0c;为C开发者带来了正则表达式库&#xff0c;极大地丰富了C在文本处理方面的能力。本文将全方位、多角度地深入探讨C11正则表达式库&#…

c语言----------内存管理

内存管理 目录 一。作用域1.1 局部变量1.2 静态(static)局部变量1.3 全局变量1.4 静态(static)全局变量1.5 extern全局变量声明1.6 全局函数和静态函数1.7 总结 二。内存布局2.1 内存分区2.2 存储类型总结2.3内存操作函数1) memset()2) memcpy()3) memmove()4) memcmp() 2.4 堆…

机器学习-归一化

文章目录 一. 归一化二. 归一化的常见方法1. 最小-最大归一化 (Min-Max Normalization)2. Z-Score 归一化&#xff08;标准化&#xff09;3. MaxAbs 归一化 三. 归一化的选择四. 为什么要进行归一化1. 消除量纲差异2. 提高模型训练速度3. 增强模型的稳定性4. 保证正则化项的有效…

STC的51单片机LED点灯基于KEIL

前言&#xff1a; 该文源于回答一个朋友的问题&#xff0c;代码为该朋友上传&#xff0c;略作修改&#xff0c;在此说明问题以及解决问题的思路&#xff0c;以减少新手错误。 电路图&#xff1a; 该位朋友未上传电路图&#xff0c;说明如下&#xff1a; stc8g1k08a-sop8控制…

手撕Transformer -- Day6 -- DecoderBlock

手撕Transformer – Day6 – DecoderBlock 目录 手撕Transformer -- Day6 -- DecoderBlockTransformer 网络结构图DecoderBlock 代码Part1 库函数Part2 实现一个解码器Block&#xff0c;作为一个类Part3 测试 参考 Transformer 网络结构图 Transformer 网络结构 DecoderBlock 代…

【功能测试总结】

功能测试 1. 功能测试用例1.1 设计用例容易出现的问题 2. 如何写用例2.1 什么是好的用例2.2 测试用例设计常见方法 3. 用例分级 1. 功能测试用例 1.1 设计用例容易出现的问题 基础功能点用例覆盖不全/描述不清 描述不清 什么是正常内容&#xff0c;仅看用例能否知道该输入什么…

Mac玩Steam游戏秘籍!

Mac玩Steam游戏秘籍&#xff01; 大家好&#xff01;最近有不少朋友在用MacBook玩Steam游戏时遇到不支持mac的问题。别担心&#xff0c;我来教你如何用第三方工具Crossover来畅玩这些不支持的游戏&#xff0c;简单又实用&#xff01; 第一步&#xff1a;下载Crossover 首先&…

基于Springboot + vue实现的旅游网站

&#x1f942;(❁◡❁)您的点赞&#x1f44d;➕评论&#x1f4dd;➕收藏⭐是作者创作的最大动力&#x1f91e; &#x1f496;&#x1f4d5;&#x1f389;&#x1f525; 支持我&#xff1a;点赞&#x1f44d;收藏⭐️留言&#x1f4dd;欢迎留言讨论 &#x1f525;&#x1f525;&…

题解 CodeForces 430B Balls Game 栈 C/C++

题目传送门&#xff1a; Problem - B - Codeforceshttps://mirror.codeforces.com/contest/430/problem/B翻译&#xff1a; Iahub正在为国际信息学奥林匹克竞赛&#xff08;IOI&#xff09;做准备。有什么比玩一个类似祖玛的游戏更好的训练方法呢&#xff1f; 一排中有n个球…

Vue3播放视频报ReferenceError: SharedArrayBuffer is not defined

解决办法 前端本地测试vue.config.js server: {headers: {"Cross-Origin-Opener-Policy": "same-origin","Cross-Origin-Embedder-Policy": "require-corp",}, }, 后端vue.js生产环境 跨域隔离 是一种现代Web安全策略&#xff0c;…

Android BottomNavigationView不加icon使text垂直居中,完美解决。

这个问题网上千篇一律的设置iconsize为0&#xff0c;labale固定什么的&#xff0c;都没有效果。我的这个基本上所有人用都会有效果。 问题解决之前的效果&#xff1a;垂直方向&#xff0c;文本不居中&#xff0c;看着很难受 问题解决之后&#xff1a;舒服多了 其实很简单&…

微调神经机器翻译模型全流程

MBART: Multilingual Denoising Pre-training for Neural Machine Translation 模型下载 mBART 是一个基于序列到序列的去噪自编码器&#xff0c;使用 BART 目标在多种语言的大规模单语语料库上进行预训练。mBART 是首批通过去噪完整文本在多种语言上预训练序列到序列模型的方…

基于32QAM的载波同步和定时同步性能仿真,包括Costas环的gardner环

目录 1.算法仿真效果 2.算法涉及理论知识概要 3.MATLAB核心程序 4.完整算法代码文件获得 1.算法仿真效果 matlab2022a仿真结果如下&#xff08;完整代码运行后无水印&#xff09;&#xff1a; 仿真操作步骤可参考程序配套的操作视频。 2.算法涉及理论知识概要 载波同步是…

设计模式-工厂模式/抽象工厂模式

工厂模式 定义 定义一个创建对象的接口&#xff0c;让子类决定实列化哪一个类&#xff0c;工厂模式使一个类的实例化延迟到其子类&#xff1b; 工厂方法模式是简单工厂模式的延伸。在工厂方法模式中&#xff0c;核心工厂类不在负责产品的创建&#xff0c;而是将具体的创建工作…

【机器学习】零售行业的智慧升级:机器学习驱动的精准营销与库存管理

我的个人主页 我的领域&#xff1a;人工智能篇&#xff0c;希望能帮助到大家&#xff01;&#xff01;&#xff01;&#x1f44d;点赞 收藏❤ 在当今数字化浪潮汹涌澎湃的时代&#xff0c;零售行业正站在转型升级的十字路口。市场竞争的白热化使得企业必须另辟蹊径&#xff0…

day_2_排序算法和树

文章目录 排序算法和树排序算法算法稳定性排序算法☆ 冒泡排序冒泡思路冒泡步骤代码实现效率优化 ☆ 选择排序排序思路排序步骤代码实现 ... 树01-树的基本概念02-树的相关术语03-二叉树的种类04-二叉树的存储05-树的应用场景_数据库索引06-二叉树的概念和性质07-广度优先遍历0…

蓝桥杯刷题第二天——背包问题

题目描述 有N件物品和一个容量是V的背包。每件物品只能使用一次。第i件物品的体积是Vi价值是Wi。 求解将哪些物品装入背包&#xff0c;可使这些物品的总体积不超过背包容量&#xff0c;且总价值最大。 输出最大价值。 输入格式 第一行两个整数&#xff0c;N&#xff0c;V&am…

Linux x86_64 程序动态链接之GOT 和 PLT

文章目录 前言一、动态链接二、位置无关代码三、GOT 和 PLT3.1 GOT3.2 PLT3.3 延时绑定3.4 示例 四、demo演示五、延迟绑定技术和代码修补参考资料 前言 这篇文章描述了&#xff1a;Linux x86_64 程序静态链接之重定位&#xff0c;接来本文描述Linux x86_64 程序动态链接之GOT…

学习记录-责任链模式验证参数

学习记录-责任链模式验证参数 1.什么是责任链模式 责任链模式&#xff08;Chain of Responsibility Pattern&#xff09;是一种行为设计模式&#xff0c;它允许将请求沿着一个处理链传递&#xff0c;直到链中的某个对象处理它。这样&#xff0c;发送者无需知道哪个对象将处理…