学习c++的第十三天

news2025/1/9 23:10:06

目录

文件和流

打开文件

关闭文件

写入文件

读取文件

读取 & 写入实例

文件位置指针

异常处理

扩展知识

抛出异常

标准的异常

定义新的异常


文件和流

到目前为止,我们已经使用了 iostream 标准库,它提供了 cin 和 cout 方法分别用于从标准输入读取流和向标准输出写入流。

本教程介绍如何从文件读取流和向文件写入流。这就需要用到 C++ 中另一个标准库 fstream,它定义了三个新的数据类型:

数据类型描述
ofstream该数据类型表示输出文件流,用于创建文件并向文件写入信息。
ifstream该数据类型表示输入文件流,用于从文件读取信息。
fstream该数据类型通常表示文件流,且同时具有 ofstream 和 ifstream 两种功能,这意味着它可以创建文件,向文件写入信息,从文件读取信息。

要在 C++ 中进行文件处理,必须在 C++ 源代码文件中包含头文件 <iostream> 和 <fstream>。

打开文件

打开文件是进行读写操作之前的必要步骤。在 C++ 中,我们使用流对象的 open() 成员函数来打开文件。

下面是 open() 函数的标准语法:

void open(const char* filename, std::ios::openmode mode);

在这里,open() 成员函数的第一个参数指定要打开的文件的名称和位置,第二个参数定义文件被打开的模式,即 std::ios::openmode。

模式标志描述
ios::app追加模式。所有写入都追加到文件末尾。
ios::ate文件打开后定位到文件末尾。
ios::in打开文件用于读取。
ios::out打开文件用于写入。
ios::trunc如果该文件已经存在,其内容将在打开文件之前被截断,即把文件长度设为 0。

您可以把以上两种或两种以上的模式结合使用。例如,如果您想要以写入模式打开文件,并希望截断文件,以防文件已存在,那么您可以使用下面的语法:

ofstream outfile;
outfile.open("file.dat", ios::out | ios::trunc );

 类似地,您如果想要打开一个文件用于读写,可以使用下面的语法:

ifstream  afile;
afile.open("file.dat", ios::out | ios::in );

关闭文件

当 C++ 程序终止时,它会自动关闭刷新所有流,释放所有分配的内存,并关闭所有打开的文件。但程序员应该养成一个好习惯,在程序终止前关闭所有打开的文件。在 C++ 中,我们使用流对象的 close() 成员函数来关闭文件。

下面是 close() 函数的标准语法:

void close();

写入文件

在C++中,我们可以使用流插入运算符(<<)将数据写入文件。与将数据输出到屏幕上的情况类似,只需要将输出目标从cout对象更改为ofstream或fstream对象。

下面是一个简单的示例代码,演示了如何使用ofstream对象向文件写入信息:

#include <fstream>

int main() {
    std::ofstream outfile("example.txt"); // 打开文件进行写入操作

    if (outfile.is_open()) {
        outfile << "Hello, World!" << std::endl; // 使用流插入运算符写入信息到文件
        outfile << "This is a line of text." << std::endl;
        outfile.close(); // 关闭文件
        std::cout << "File written successfully." << std::endl;
    } else {
        std::cout << "Unable to open file." << std::endl;
    }

    return 0;
}

在这个示例中,我们创建了一个名为outfile的ofstream对象,并将文件名作为构造函数的参数传递给它。通过使用流插入运算符(<<),我们可以将文本写入到文件中。在这个示例中,我们写入了两行文本并在每行末尾添加了换行符。最后,我们使用close()函数关闭文件。

需要注意的是,在进行文件写入操作时,需要确保文件存在并具有适当的写入权限。如果文件不存在,ofstream对象将会自动创建一个新文件。

读取文件

在C++中,使用流提取运算符(>>)从文件中读取信息是不安全的,因为它无法正确处理包含空格的字符串。如果文件中的信息包含空格,则会导致信息读取错误。

相反,在C++中,我们通常使用getline()函数从文件中逐行读取信息。getline()函数可以正确处理包含空格的字符串。下面是一个读取文件的示例代码:

#include <fstream>
#include <iostream>
#include <string>

int main()
{
    std::ifstream infile("example.txt"); // 打开文件进行读取操作

    if (infile.is_open())
    {
        std::string line;
        while (std::getline(infile, line)) // 逐行读取文件内容
        {
            std::cout << line << std::endl; // 在控制台输出读取到的内容
        }
        infile.close(); // 关闭文件
    }
    else
    {
        std::cout << "Unable to open file." << std::endl;
    }

    return 0;
}

在上述示例中,我们创建了一个 ifstream 对象 infile 并将文件名作为构造函数的参数传递给它。然后,我们使用 std::getline() 函数逐行读取文件内容,并将读取的每一行输出到控制台。

需要注意的是,在进行文件读取操作时,需要确保文件存在并具有适当的读取权限。

读取 & 写入实例

下面的 C++ 程序以读写模式打开一个文件。在向文件 afile.dat 写入用户输入的信息之后,程序从文件读取信息,并将其输出到屏幕上:

#include <fstream>
#include <iostream>
#include <string>

int main()
{
    std::ofstream outfile("afile.dat", std::ios::out | std::ios::binary); // 以写模式打开文件

    if (outfile.is_open())
    {
        std::cout << "输入一些文本: ";
        std::string input;
        std::getline(std::cin, input);

        outfile.write(input.c_str(), input.size()); // 将用户输入的信息写入文件

        outfile.close(); // 关闭文件
        std::cout << "文件写入成功." << std::endl;
    }
    else
    {
        std::cout << "无法打开文件." << std::endl;
    }

    std::ifstream infile("afile.dat", std::ios::in | std::ios::binary); // 以读模式打开文件

    if (infile.is_open())
    {
        std::string line;
        std::getline(infile, line); // 从文件读取信息
        std::cout << "文件内容: " << line << std::endl;

        infile.close(); // 关闭文件
    }
    else
    {
        std::cout << "Unable to open file." << std::endl;
    }

    return 0;
}

在上述示例中,我们首先使用 std::ofstream 对象以写模式打开文件 afile.dat,然后通过 write() 函数将用户输入的信息写入文件。接着关闭文件,并输出写入成功的提示。

然后,我们使用 std::ifstream 对象以读模式打开同一个文件,通过 getline() 函数从文件中读取信息,并将读取到的信息输出到屏幕上。

需要注意的是,我们在打开文件时使用了 std::ios::binary 模式,这样可以确保以二进制方式进行读写操作,并适用于包含二进制数据的文件。

同时,为了正确处理用户输入的字符串,我们使用 std::getline() 函数而不是流提取运算符(>>)来读取用户输入的信息。这样可以确保读取整行内容,包括空格等特殊字符。

文件位置指针

对于 istream 类型(如 ifstream),可以使用成员函数 seekg() 来重新定位文件位置指针。seekg() 函数的参数通常是一个长整型值,表示要定位的偏移量。第二个参数可以指定查找方向,可以是 ios::beg(从流的开头开始定位),也可以是 ios::cur(从流的当前位置开始定位),也可以是 ios::end(从流的末尾开始定位)。

下面是一个示例代码,演示了如何使用 seekg() 函数定位 "get" 文件位置指针:

#include <iostream>
#include <fstream>

int main()
{
    std::ifstream infile("output.txt", std::ios::in | std::ios::binary);

    if (infile.is_open())
    {
        // 获取当前文件位置指针
        std::streampos currentPosition = infile.tellg();
        std::cout << "当前位置: " << currentPosition << std::endl;

        // 重新定位文件位置指针到文件开头
        infile.seekg(0, std::ios::beg);
        std::cout << "寻找开始后的位置: " << infile.tellg() << std::endl;

        // 重新定位文件位置指针到文件末尾
        infile.seekg(0, std::ios::end);
        std::cout << "寻找到底后的位置: " << infile.tellg() << std::endl;

        // 重新定位文件位置指针到文件中间
        infile.seekg(currentPosition, std::ios::beg);
        std::cout << "中间位置: " << infile.tellg() << std::endl;

        infile.close();
    }
    else
    {
        std::cout << "无法打开文件。" << std::endl;
    }

    return 0;
}

在上述示例中,我们首先使用 tellg() 函数获取了当前的文件位置指针,并将其保存在 currentPosition 变量中。然后,我们使用 seekg() 函数将文件位置指针分别定位到文件的开头、末尾和中间,并使用 tellg() 函数输出了定位后的位置。

需要注意的是,文件位置指针是一个整数值,它表示从文件的起始位置到指针所在位置的字节数。tellg() 函数返回的也是一个整数值,表示当前的文件位置指针。

类似地,对于 ostream 类型(如 ofstream),可以使用成员函数 seekp() 来重新定位文件位置指针。seekp() 的用法与 seekg() 类似,只是它用于定位 "put" 文件位置指针(即写入操作)。

异常处理

在C++中,异常处理是一种机制,用于处理程序在运行过程中发生的异常情况。异常是指在程序执行期间发生的意外或错误情况,可能导致程序无法正常执行下去。

C++提供了一个异常处理的机制,使用关键字 try、catch 和 throw 来实现。以下是异常处理的基本语法:

try {
    // 可能会引发异常的代码块
}
catch (ExceptionType1 exception1) {
    // 处理 ExceptionType1 异常的代码块
}
catch (ExceptionType2 exception2) {
    // 处理 ExceptionType2 异常的代码块
}
...
catch (ExceptionTypeN exceptionN) {
    // 处理 ExceptionTypeN 异常的代码块
}

在 try 块中,放置可能会引发异常的代码。如果在 try 块中发生异常,则会立即跳转到最匹配的 catch 块,并执行相应的异常处理代码。catch 块按顺序进行匹配,直到找到与抛出的异常类型匹配的块。一旦找到匹配的 catch 块,后续的块将被忽略。

异常类型可以是标准的 C++ 异常类,也可以是用户自定义的异常类。catch 块中的参数是接收异常对象的变量,在 catch 块中可以使用该变量来处理异常。

在 catch 块中,可以执行与异常相关的处理逻辑,如输出错误消息、记录日志或进行恢复操作。如果没有找到匹配的 catch 块,异常将会传播到调用函数的上层,并继续寻找匹配的 catch 块。

扩展知识

c++异常机制为什么没有finally?

在C++中,确实没有像其他编程语言(如Java和C#)中的 finally 关键字那样提供一个专门的块来处理无论是否发生异常都必须执行的代码。有几个原因可以解释为什么C++没有引入 finally 关键字:

  • 简洁性:C++的设计原则之一是保持语言简洁,避免引入不必要的复杂性。引入 finally 关键字可能会增加语法复杂性,对于大多数情况下不需要执行特定代码的开发者来说,这可能会造成混淆。
  • 资源管理:C++重视资源管理的灵活性,通过使用析构函数和智能指针等机制来自动处理资源的释放。这种资源管理方式可以在对象生命周期结束时自动调用析构函数进行资源清理,而无需显式地使用 finally 块。
  • 异常安全性:C++的异常处理机制本身提供了异常安全性的支持。异常安全性是指程序在处理异常时能够正确地释放已分配的资源,以避免资源泄漏或数据不一致。通过适当的资源管理和异常处理,可以实现异常安全的代码,而不需要额外的 finally 块。

尽管C++没有提供 finally 关键字,但可以通过其他方式来实现类似的功能。例如,可以使用RAII(资源获取即初始化)技术来管理资源,确保在任何情况下都会正确释放资源。此外,可以在 try 块中添加适当的清理代码,以处理在发生异常时需要执行的特定操作。

以下是一个示例,演示了如何使用RAII和适当的清理代码来模拟 finally 的行为:

#include <iostream>
#include <fstream>

class FileHandler
{
public:
    FileHandler(const std::string& filename)
        : file(filename)
    {
        // 打开文件
        if (!file.is_open())
        {
            throw std::runtime_error("无法打开文件.");
        }
    }

    ~FileHandler()
    {
        // 关闭文件
        file.close();
    }

    void writeData(const std::string& data)
    {
        // 写入数据到文件
        file << data;
    }

private:
    std::ofstream file;
};

int main()
{
    try
    {
        FileHandler file("output.txt");
        file.writeData("Hello, World!");
        // 在这里可以执行其他操作,不必担心资源泄漏

        // 如果在这之后发生异常,FileHandler 的析构函数会确保文件被关闭
        throw std::runtime_error("出了问题.");
    }
    catch (const std::exception& e)
    {
        std::cerr << "捕获到异常: " << e.what() << std::endl;
    }

    return 0;
}

在上述示例中,我们定义了一个 FileHandler 类,用于打开文件并在析构函数中关闭文件。在 main() 函数中,我们使用 FileHandler 对象来打开文件,并在 writeData() 函数中写入数据。无论发生何种情况,当 FileHandler 对象的生命周期结束时,析构函数会被自动调用,确保文件被正确关闭。

需要注意的是,虽然C++没有 finally 关键字,但仍然可以通过适当的代码设计和资源管理来实现相似的功能,并确保代码在异常情况下能够正确处理资源。

抛出异常

除了 try-catch 块,在C++中,还可以使用 throw 语句抛出异常,抛出的异常可以是任何类型的对象,但通常建议使用标准库中定义的异常类(如 std::exception 或其子类)来表示异常。抛出异常的一般语法如下:

throw SomeExceptionType("Exception message");

其中,SomeExceptionType 是指异常对象的类型,可以是任何类型,但通常是从 std::exception 类派生的自定义异常类。"Exception message" 是一个字符串,用于描述异常的详细信息。

例如,下面的代码演示了如何抛出一个 std::runtime_error 异常:

#include <stdexcept>
#include <iostream>

void myFunction(int a, int b)
{
    if (b == 0)
    {
        throw std::runtime_error("除以零");
    }

    std::cout << "a / b = " << a / b << std::endl;
}

int main()
{
    try
    {
        myFunction(10, 2);
        myFunction(20, 0); // 这里会抛出一个异常
        myFunction(30, 3);
    }
    catch (const std::exception& e)
    {
        std::cerr << "捕捉到异常: " << e.what() << std::endl;
    }

    return 0;
}

在上述示例中,myFunction() 函数接受两个参数 a 和 b,并检查 b 是否为零。如果 b 为零,则抛出一个 std::runtime_error 异常。在 main() 函数中,我们调用 myFunction() 三次,当第二次调用时会抛出一个异常,此时程序将跳转到 catch 块中,输出异常信息并继续执行后续代码。

需要注意的是,在抛出异常之前应该确保资源得到了正确的释放,否则可能会导致资源泄漏或数据不一致。通常情况下,可以使用 RAII 技术来管理资源,并确保资源能在对象生命周期结束时自动释放,即使发生异常也能正确地处理资源。

标准的异常

在C++中,标准库 <exception> 提供了一系列的异常类,这些异常类用于表示不同类型的异常情况。它们以父子类层次结构组织起来。这些异常类都继承自 std::exception 类,它本身也是一个异常类。通过捕获和处理这些异常,我们可以在程序出现错误时采取适当的措施或提供有用的错误信息,使程序更加健壮和可靠。如下所示:

下面是对每个异常的详细说明:

  1. std::exception:该异常是所有标准C++异常的父类。

  2. std::bad_alloc:该异常可以通过new抛出,表示在动态内存分配过程中无法分配所需的内存。

  3. std::bad_cast:该异常可以通过dynamic_cast抛出,表示类型转换失败。

  4. std::bad_typeid:该异常可以通过typeid运算符抛出,表示无效的类型标识符。

  5. std::bad_exception:这个异常在处理C++程序中无法预期的异常时非常有用。

  6. std::logic_error:理论上可以通过读取代码来检测到的异常,表示程序逻辑错误。

  7. std::domain_error:当使用了一个无效的数学域时,比如在执行数学函数时传入了无效的参数,会抛出该异常。

  8. std::invalid_argument:当使用了无效的参数时,比如传入了一个无效的参数值,会抛出该异常。

  9. std::length_error:当创建了太长的std::string对象时,会抛出该异常。

  10. std::out_of_range:该异常可以通过某些方法抛出,比如在使用std::vector或std::bitset<>::operator时,当索引超出范围时会抛出该异常。

  11. std::runtime_error:理论上不可以通过读取代码来检测到的异常,表示在运行时发生的错误。

  12. std::overflow_error:当发生数学上溢时,比如在执行算术运算时结果超出了数据类型的表示范围,会抛出该异常。

  13. std::range_error:当尝试存储超出范围的值时,比如在执行数学运算时结果超出了数据类型的表示范围,会抛出该异常。

  14. std::underflow_error:当发生数学下溢时,比如在执行算术运算时结果小于了数据类型的最小值,会抛出该异常。

这些标准异常类提供了一种统一的机制来处理和报告可能发生的异常情况,我们可以根据具体的异常类型来采取相应的处理措施。

定义新的异常

可以通过继承和重载std::exception类来定义新的异常。通过自定义异常类,可以根据特定的应用程序需求定义和抛出自己的异常类型。

下面是一个示例:

#include <iostream>
#include <exception>
#include <string>

class MyException : public std::exception
{
public:
    MyException(const std::string& message) : m_message(message) {}

    const char* what() const noexcept override
    {
        return m_message.c_str();
    }

private:
    std::string m_message;
};

在上面的示例中,我们定义了一个名为MyException的自定义异常类,它继承自std::exception类。我们在构造函数中接受一个字符串参数作为异常消息,并将其保存在私有成员变量m_message中。

我们还重载了what()方法,它是std::exception类的虚函数。what()方法返回一个指向异常消息的C风格字符串。在这个示例中,我们简单地返回了保存的异常消息。

现在,我们可以在程序中使用MyException异常类,并在需要的地方抛出它:

void foo()
{
    throw MyException("Something went wrong!");
}

int main()
{
    try
    {
        foo();
    }
    catch (const MyException& e)
    {
        // 处理自定义异常
        std::cout << "Caught exception: " << e.what() << std::endl;
    }
    catch (const std::exception& e)
    {
        // 处理其他标准异常
        std::cout << "Caught exception: " << e.what() << std::endl;
    }

    return 0;
}

在上面的示例中,我们在foo()函数中抛出了一个MyException异常,并在main()函数中使用try-catch块捕获并处理它。在catch块中,我们可以根据异常的类型来执行相应的操作。

这样,就可以定义和使用自己的异常类来处理特定的异常情况,并提供有用的错误信息。请记住,在自定义异常类时,继承自std::exception是一种良好的实践,可以使您的异常类与标准异常类保持一致,并符合C++异常处理的规范。

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

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

相关文章

一文搞懂优先队列及相关算法

大家好&#xff0c;我是 方圆。优先队列在 Java 中的定义是 PriorityQueue&#xff0c;它基于 二叉堆 数据结构实现&#xff0c;其中的元素并不是全部有序&#xff0c;但它能够支持高效地 获取或删除最值元素。 二叉堆是一种特定条件的 完全二叉树&#xff0c;树的根节点为堆顶…

vivo 网络端口安全建设技术实践

作者&#xff1a;vivo 互联网安全团队 - Peng Qiankun 随着互联网业务的快速发展&#xff0c;网络攻击的频率和威胁性也在不断增加&#xff0c;端口是应用通信中的门户&#xff0c;它是数据进出应用的必经之路&#xff0c;因此端口安全也逐渐成为了企业内网的重要防线之一&…

公司团建小游戏开发小程序游戏互动小游戏

在现代工作环境中&#xff0c;团队合作和员工士气是取得成功的关键因素。为了增强团队合作、提升员工士气&#xff0c;并促进员工之间的互动&#xff0c;公司团建小游戏成为了一种备受欢迎的方式。本文将探讨如何开发公司团建小游戏&#xff0c;以达到这些目标。 1. 游戏概念 …

2023下半年软考信息系统项目管理师上午真题及答案

1.( B )不属于项目建议书的核心内容。 A.项目的必要性 B.初步可行性研究 C.项目的市场预测 D.项目建设必需的条件 解析&#xff1a; 2.在监控项目工作过程中&#xff0c;当遇到变更请求时&#xff0c;为使项目工作绩效重新与项目管理计划致&#xff0c;而进行的有目的的活动…

【双指针+简化去重操作】Leetcode 15 三数之和

【双指针简化操作】Leetcode 15 三数之和 解法1 解法1 新建一个嵌套列表&#xff1a;List<List<Integer>> result new List<>(); 初始化一个ArrayList并直接赋值&#xff1a;ArrayList<Integer> result new ArrayList<>(Arrays.asList(1, 2…

又来安利了,这个Itbuilder在线数据库设计工具用起来太顺手了

对于测试、开发、DBA、运维来说&#xff0c;数据库是再熟悉不过了。 我们都知道如今的数据是多么复杂和难以管理&#xff0c;但幸运的是有数据库设计工具可以帮助我们&#xff0c;可以在市场上找到很多的数据库设计工具&#xff0c;包括itbuilder。这些数据库设计工具可以帮助我…

如何选择SVM中最佳的【核函数】

参数“kernel"在sklearn中可选以下几种 选项&#xff1a; 接下来我们 就通过一个例子&#xff0c;来探索一下不同数据集上核函数的表现。我们现在有一系列线性或非线性可分的数据&#xff0c;我们希望通过绘制SVC在不同核函数下的决策边界并计算SVC在不同核函数下分类准确…

如何对ppt文件设置修改权限?

PPT文件会应用在会议、演讲、课件等工作生活中&#xff0c;当我们制作好了PPT之后&#xff0c;保护内容防止在演示时出错是很重要的&#xff0c;那么如何将PPT文件设置成禁止修改模式呢&#xff1f;今天分享几个方法给大家。 方法一 将PPT文件直接保存或者另存为一份文件&…

【Effective Modern C++】条款2:理解auto类型推导

条款2&#xff1a;理解auto类型推导 条款1中&#xff0c;模板类型推导的函数模板形如&#xff1a; template<typename T> void f(ParamType param);当变量采用auto声明时&#xff0c;auto扮演了模板中的T这个角色&#xff0c;而变量的类型扮演的是ParamType的角色。 条…

如何提高CRM系统的使用率?

​ CRM客户管理系统采购以后不投入使用&#xff0c;或者用了却用不好&#xff0c;都是极大的浪费。在知道CRM系统使用率低的原因之后&#xff0c;就要通过有效的方法提升CRM使用率。下面整理了六个方法&#xff0c;告诉您如何提高CRM系统的使用率。 有人演奏不出优美的曲子&a…

本地如何安装多个node版本

使用nvm 1官网下载 Releases coreybutler/nvm-windows GitHub 2.安装完 nvm -v检查是否按照成功 三、nvm的使用 安装完毕后&#xff0c;找到安装的路径&#xff0c;一些简单配置&#xff0c;打开setting.txt (是下载完毕之后自动帮你生成npm 下载node包之后不用重复安装…

【23真题】满分!最高150分!评级A+!

今天分享的是23年西南交通大学924的信号与系统试题及解析。这套卷子是回忆版&#xff0c;我已经尽力去还原了&#xff0c;全网仅此一份。如果有疏漏的地方&#xff0c;欢迎大家和我反馈。 本套试卷难度分析&#xff1a;平均分在124分&#xff0c;最高分有满分150分&#xff01…

高清Logo素材无忧:这5个网站解决所有问题!

今天给大家分享几个素材网站&#xff0c;基本上可以下载各大企业的 Logo&#xff0c;而且还是矢量格式哦~ 即时设计 即时设计是一款国产免费的 Logo 在线设计制作工具&#xff0c;浏览器内打开即用&#xff0c;对于使用系统没有任何限制。在即时设计&#xff0c;你可以从 0 到…

【数智化案例展】正官庄——全球商业数智化实践案例

‍ Marketingforce案例 本项目案例由Marketingforce投递并参与数据猿与上海大数据联盟联合推出的《2023中国数智化转型升级创新服务企业》榜单/奖项”评选。 大数据产业创新服务媒体 ——聚焦数据 改变商业 电商行业持续发展&#xff0c;而对于品牌来说&#xff0c;面对多个分…

陈海波:OpenHarmony技术领先,产学研深度协同,生态蓬勃发展

11月4日&#xff0c;以“技术筑生态&#xff0c;智联赢未来”为主题的第二届OpenHarmony技术大会在北京隆重举办。本次大会由OpenAtom OpenHarmony&#xff08;简称“OpenHarmony"&#xff09;项目群技术指导委员会&#xff08;TSC&#xff09;主办&#xff0c;由华为技术…

第十一章 Python 常用标准库

系列文章目录 第一章 Python 基础知识 第二章 python 字符串处理 第三章 python 数据类型 第四章 python 运算符与流程控制 第五章 python 文件操作 第六章 python 函数 第七章 python 常用内建函数 第八章 python 类(面向对象编程) 第九章 python 异常处理 第十章 python 自定…

解决Lightroom Classic无法使用修改照片的问题

Lightroom Classic是一款广泛使用的照片编辑软件&#xff0c;但在使用过程中&#xff0c;可能会遇到无法修改照片的问题。修改照片这个模块无法使用&#xff0c;功能按钮呈现灰色&#xff0c;无法点击。本文将介绍几种常见的解决方法&#xff0c;帮助您快速解决Lightroom无法使…

Banana Pi BPI-W3 RK3588平台驱动调试篇 [ PCIE篇一 ] - PCIE的开发指南

RK3588平台驱动调试篇 [ PCIE篇 ] - PCIE的开发指南 1、PCIE接口概述 PCIe&#xff08;Peripheral Component Interconnect Express&#xff09;是一种用于连接计算机内部组件的高速接口标准。以下是关于PCIe接口的简要介绍&#xff1a; 高速传输&#xff1a; PCIe接口提供了…

springboot 文件上传 阿里云OSS

一、介绍 文件上传&#xff0c;是指将本地图片、视频、音频等文件上传到服务器上&#xff0c;可以供其他用户浏览或下载的过程。文件上传在项目中应用非常广泛&#xff0c;我们经常发抖音、发朋友圈都用到了文件上传功能。 实现文件上传服务&#xff0c;需要有存储的支持&…

01-Spring中事务的实现和事务的属性

银行账户转账异常 需求: 实现act-001账户向act-002账户转账10000,要求两个账户的余额一个减成功一个加成功,即执行的两条update语句必须同时成功或失败 实现步骤 第一步: 引入项目所需要的依赖 <?xml version"1.0" encoding"UTF-8"?> <proj…