当前位置: 首页 > news >正文

RandomAccessFile学习笔记

文章目录

  • RandomAccessFile学习笔记
    • 前言
    • 1、RandomAccessFile基本介绍
      • 1.1 RandomAccessFile相关基本概念
      • 1.2 RandomAccessFile家族体系
    • 2、RandomAccessFile基本使用
      • 2.1 RandomAccessFile常用API介绍
      • 2.2 RandomAccessFile常用API演示
      • 2.3 RandomAccessFile实现断点续传

RandomAccessFile学习笔记

前言

本文将简要介绍RandomAccessFile这个类的使用,主要包括RandomAccessFile相关的一些概念,常见API的使用,如何利用RandomAccessFile实现一个断点续传的效果

1、RandomAccessFile基本介绍

1.1 RandomAccessFile相关基本概念

  • RandomAccessFile是什么

    RandomAccessFile 是 Java 中用于对文件进行随机访问的类。与普通的输入输出流不同,RandomAccessFile 允许在文件中任意位置读写数据。

  • RandomAccessFile的作用有哪些

    • 随机访问:与其他输入输出流不同,RandomAccessFile 允许在文件中任意位置进行读写操作,可以自由地定位文件指针。
    • 读写基本数据类型RandomAccessFile 实现了 DataInputDataOutput 接口,提供了方便的方法用于读取和写入基本数据类型。
    • 支持读写字节数组:除了读写基本数据类型外,还可以通过 read(byte[] buffer)write(byte[] buffer) 方法来读写字节数组。
    • 支持文件截断:可以使用 setLength(long newLength) 方法来调整文件的长度,将文件截断或扩展为指定的大小。

    常见的应用场景是使用 RandomAccessFile 实现断点续传

    注意事项RandomAccessFile只能读写文件(也就是字节数组)类型的数据,并不能读写流类型的数据

  • RandomAccessFile的四种访问模式

    访问模式特点
    r(read,只读模式)能读文件,不能写文件、持久化
    rw(read write,读写模式)能读、写文件,不能持久化
    rws(read write sync,同步读写模式)能读、写文件,每次写操作都会持久化
    rwd(read write data,同步写模式)能读、写文件,只有在调用close()、getFD().sync()、关闭程序时才进行持久化
    • r”(只读模式):使用只读模式打开文件,只能对文件进行读取操作,无法修改文件内容。
    • rw”(读写模式):使用读写模式打开文件,允许对文件进行读取和写入操作,并且可以修改文件内容。
    • rws”(同步读写模式):使用同步读写模式打开文件,除了具有读写模式的功能外,还要求每次写入操作都要将数据同步刷新到底层存储介质(如硬盘)。在使用 rws 模式打开文件时,每次进行写入操作时,不仅会将数据写入到内存缓冲区,还会立即将数据刷新到底层存储介质(如硬盘)。这样可以保证数据的持久性,并且在发生系统崩溃或断电等异常情况时,数据不会丢失。由于每次写入操作都要进行磁盘刷新,所以相比于 rwd 模式,rws 模式的写入速度可能较慢。
    • rwd”(同步写模式):使用同步写模式打开文件,类似于同步读写模式,在使用 rwd 模式打开文件时,每次进行写入操作时,只有将数据写入到内存缓冲区,而不会立即刷新到底层存储介质。只有在调用 close() 方法、显式调用 getFD().sync() 方法或关闭程序时,才会将数据刷新到存储介质。相比于 rws 模式,rwd 模式的写入速度可能稍快,因为不需要每次都进行磁盘刷新。

    适用场景说明:

    1. 如果文件只需要具有读操作,就使用 r 模式;
    2. 如果文件既需要读又需要写,同时对持久化没有要求,就可以用 rw 模式;
    3. 如果文件既需要读又需要写,同时对持久化有要求严格或者是读多写少的情况,推荐使用 rws 模式
    4. 如果文件既需要读又需要写,同时对持久化有要求不是很严格 或者是 读少写多,推荐使用 rwd 模式

1.2 RandomAccessFile家族体系

  • RandomAccessFile家族体系

    image-20230826185124272

    image-20230826185142134

    • java.io.DataOutputDataOutput 接口提供了写入基本数据类型的方法,用于将数据以二进制格式写入输出流。RandomAccessFile 类实现了 DataOutput 接口,因此可以使用该接口定义的方法写入数据。
    • java.io.DataInputDataInput 接口定义了读取基本数据类型的方法,用于从输入流中以二进制格式读取数据。RandomAccessFile 类实现了 DataInput 接口,因此可以使用该接口定义的方法读取数据。
    • java.io.CloseableCloseable 是一个可关闭的接口,表示实现了该接口的类具备关闭资源的能力。RandomAccessFile 类实现了 Closeable 接口,因此可以通过调用 close() 方法关闭文件。
    • java.lang.AutoCloseableAutoCloseable 是一个自动关闭的接口,在 Java 7 中引入。它扩展了 Closeable 接口,并要求实现类必须提供一个细化的 close() 方法。RandomAccessFile 实现了 AutoCloseable 接口,所以可以使用 try-with-resources 语句来自动关闭文件。

2、RandomAccessFile基本使用

2.1 RandomAccessFile常用API介绍

  • 构造方法

    • RandomAccessFile(String name, String mode):创建一个具有指定名称的RandomAccessFile对象,并根据指定的模式打开文件。模式可以是"r"(只读),“rw”(读写)等。
  • 读取方法

    • int read():从文件中读取一个字节并返回该字节的整数值。

    • int read(byte[] b):从文件中读取一定数量的字节并存储到字节数组b中,并返回实际读取的字节数。

    • int read(byte[] b, int off, int len):从文件中读取最多len个字节,并将其存储到字节数组b中,偏移量为off,并返回实际读取的字节数。

    • int skipBytes(int n):跳过指定字节读(相对位置

  • 写入方法

    • void write(int b):将一个字节写入文件。

    • void write(byte[] b):将字节数组b中的所有字节写入文件。

    • void write(byte[] b, int off, int len):将字节数组b中从偏移量off开始的len个字节写入文件。

  • 文件操作方法

    • boolean exists():判断文件是否存在。

    • void createNewFile():创建一个新文件。

    • boolean delete():删除文件。

    • boolean renameTo(File dest):将文件重命名为dest指定的文件名。

    • long getFilePointer():返回当前文件指针的位置。

    • void seek(long pos):设置文件指针的位置为pos。(绝对位置

  • 文件长度相关方法

    • long length():返回文件的长度(以字节为单位)。

    • void setLength(long newLength):设置文件的长度为newLength。

  • 关闭方法

    • void close():关闭该RandomAccessFile对象,释放相关资源

2.2 RandomAccessFile常用API演示

环境搭建

  • Step1:创建一个Maven工程

  • Step2:在src/main/resources目录下准备一个 data.txt 文件,文件中的内容是

    hello world!
    

示例一

演示read方法

    public static void main(String[] args) throws Exception {RandomAccessFile raf = new RandomAccessFile("./src/main/resources/data.txt", "r");// 读取一个字节,此时已经读取了 h,data.txt 还剩 ello world!没有读取raf.read();byte[] bytes = new byte[1024];// 将从data.txt中读取的数据转存到字节数组中int len = raf.read(bytes);// 由于在 raf.read(bytes) 之前执行过一个 raf.read() 方法了,所以此时字节数组中会直接跳过第一个字节的数组// 由于UTF-8编码英文一个字母占一个字节(中文占3个字节)所以最终结果回漏掉 data.txt 中的首字母System.out.println(new String(bytes, 0, len)); // ello world!}

备注:data.txt 中一个空格也算一个字节

示例二

演示skipBytes

    public static void main(String[] args) throws Exception {RandomAccessFile raf = new RandomAccessFile("./src/main/resources/data.txt", "r");// 读取一个字节,此时已经读取了 h,data.txt 还剩 ello world!没有读取raf.read();// 相对当前读取位置(也就是 ello world!)再跳过两个字节 e 和 l,此时 data.txt 还剩 lo world! 没有读取raf.skipBytes(2);byte[] bytes = new byte[1024];int len = raf.read(bytes);System.out.println(new String(bytes, 0, len)); // lo world!}

示例三

演示seek

    public static void main(String[] args) throws Exception {RandomAccessFile raf = new RandomAccessFile("./src/main/resources/data.txt", "r");// 读取一个字节,此时已经读取了 h,data.txt 还剩 ello world!没有读取raf.read();// 相对 data.txt 原始位置(也就是 hello world!)跳过2个字节,此时 data.txt 还剩 llo world! 没有读取raf.seek(2);byte[] bytes = new byte[1024];int len = raf.read(bytes);System.out.println(new String(bytes, 0, len)); // llo world!}

示例四

演示write

    public static void main(String[] args) throws Exception {RandomAccessFile raf = new RandomAccessFile("./src/main/resources/data.txt", "rw");// 此时直接调用write方法,是从文件的第一个字节开始写, data.txt 变成了 ghplo world!// 同时此时指针也会随着写操作来到了 lraf.write("ghp".getBytes(StandardCharsets.UTF_8));// raf.seek(0);byte[] bytes = new byte[1024];int len = raf.read(bytes);// 由于之前的写操作,导致指针来到了 l,所以读操作从 l 开始读,所以最终读取的结果是 lo world!// 并不会读取到之前写入的数据System.out.println(new String(bytes, 0, len)); // lo world!}

备注:想要写入之后能够读取到 data.txt 中完整的数据,可以在执行完写操作之后,执行seek(0)将指针重置为初始位置,注意如果使用skipBytes(0)是没有效果的,因为它是相对位置

示例五

比较 原始输入输出流单线程拷贝大文件 和 RandomAccessFile实现多线程拷贝大文件

package com.ghp.file.test;import java.io.*;
import java.util.concurrent.CountDownLatch;/*** @author ghp* @title* @description*/
public class Main {public static void main(String[] args) throws Exception {long startTime = System.currentTimeMillis();
//        copyFileBySingleThread(); // 单线程拷贝 476MB 的视频耗时 6903mscopyFileByMultiThread(); // 多线程拷贝 476MB 的视频耗时 3022mslong endTime = System.currentTimeMillis();System.out.println("文件拷贝耗时: " + (endTime - startTime) + "ms");}private static void copyFileBySingleThread() throws IOException {File file = new File("./src/main/resources/data.mp4");FileInputStream fis = new FileInputStream(file);FileOutputStream fos = new FileOutputStream("./src/main/resources/data-bak1.mp4");byte[] bytes = new byte[1024];int len = -1;while ((len = fis.read(bytes)) != -1) {fos.write(bytes, 0, len);}}private static void copyFileByMultiThread() throws Exception {File file = new File("./src/main/resources/data.mp4");int threadNum = 5;// 计算每个线程需要读取的字节大小int part = (int) Math.ceil(file.length() / threadNum);// 创建线程计数器对象,用于阻塞主线程CountDownLatch latch = new CountDownLatch(threadNum);for (int i = 0; i < threadNum; i++) {final int k = i;new Thread(() -> {try {RandomAccessFile fis = new RandomAccessFile(file, "r");RandomAccessFile fos = new RandomAccessFile("./src/main/resources/data-bak.mp4", "rw");// 设置读和写的位置fis.seek(k * part);fos.seek(k * part);byte[] bytes = new byte[1024];int sum = 0;while (true) {int len = fis.read(bytes);if (len == -1){// 文件已经读完了break;}sum += len;fos.write(bytes, 0, len);if (sum >= part){// 当前线程需要读取的字节已经读完了break;}}} catch (Exception e) {throw new RuntimeException(e);}finally {// 子线程执行完毕,线程计数器减一latch.countDown();}}).start();}// 阻塞主线程,只有线程计数器归0,主线程才会继续执行latch.await();}}

注意点

  1. 文件的切分必须是向上取整,否则回存在数据遗漏。向上取整能够保证即使多读了数据也会被覆盖避免数据遗漏,不会发生数据堆叠,而如果是向下取整就会导致数据遗漏
  2. 当前线程是否已经将自己那部分字节读取完毕的判断操作要在写操作之后,这样能够防止数据遗漏,判断操作放在写操作的后面,即使多写了数据,会被覆盖掉

2.3 RandomAccessFile实现断点续传

/*** 断点续传** @param src       源文件(需要拷贝的文件)* @param target    目标文件(拷贝后的文件)* @param threadNum 线程数*/private static void breakpointContinuation(File src, File target, int threadNum) throws Exception {// 每一个线程平均需要读取的字节数final int part = (int) Math.ceil(src.length() / threadNum);// 创建应该HashMap,用于记录每一个线程已读取的位置final Map<Integer, Integer> map = new ConcurrentHashMap<>();// 读取日志文件中的数据String[] logDatas = null;String logName = target.getCanonicalPath() + ".log";File logFile = new File(logName);if (logFile.exists()) {// 日志文件存在,则从上一次读取的位置开始读try (BufferedReader reader = new BufferedReader(new FileReader(logFile))) {String data = reader.readLine();logDatas = data.split(",");} catch (IOException e) {e.printStackTrace();}}final String[] logData = logDatas;CountDownLatch latch = new CountDownLatch(threadNum);for (int i = 0; i < threadNum; i++) {final int k = i;new Thread(() -> {try (RandomAccessFile in = new RandomAccessFile(src, "r");RandomAccessFile out = new RandomAccessFile(target, "rw");RandomAccessFile log = new RandomAccessFile(logName, "rw")) {// 从指定位置读int start = logData == null ? k * part : Integer.parseInt(logData[k]);in.seek(start);out.seek(start);byte[] bytes = new byte[1024 * 2];int sum = 0;while (true) {int len = in.read(bytes);if (len == -1) {// 文件所有字节已读完,结束读取break;}sum += len;// 记录当前线程已读取的位置map.put(k, sum + start);// 将读取到的数据、进行写入out.write(bytes, 0, len);// 将 map 中的数据持久化log.seek(0);StringJoiner joiner = new StringJoiner(",");map.forEach((key, val) -> joiner.add(String.valueOf(val)));log.write(joiner.toString().getBytes(StandardCharsets.UTF_8));if (sum + (start) >= (1 + k) * part) {// 当前线程读取的字节数量已经够了,结束读取break;}}} catch (Exception e) {e.printStackTrace();} finally {latch.countDown();}}).start();}latch.await();// 读取完成后、将日志文件删除即可new File(logName).delete();}

参考文章

  • RandomAccessFile详解_江南煮酒的博客-CSDN博客
  • Java.io.RandomAccessFile 类 (w3schools.cn)
  • RandomAccessFile 解决多线程下载及断点续传-腾讯云开发者社区-腾讯云 (tencent.com)

相关文章:

RandomAccessFile学习笔记

文章目录 RandomAccessFile学习笔记前言1、RandomAccessFile基本介绍1.1 RandomAccessFile相关基本概念1.2 RandomAccessFile家族体系 2、RandomAccessFile基本使用2.1 RandomAccessFile常用API介绍2.2 RandomAccessFile常用API演示2.3 RandomAccessFile实现断点续传 RandomAcc…...

主流数据库类型总结

前言&#xff1a;随着互联网的高速发展&#xff0c;为了满足不同的应用场景&#xff0c;数据库的种类越来越多容易混淆&#xff0c;所以有必要在此总结一下。数据库根据数据结构可分为关系型数据库和非关系型数据库。非关系型数据库中根据应用场景又可分为键值&#xff08;Key-…...

程序员养生之道

程序员养生之道——如何保持健康的生活方式 摘要&#xff1a; 随着互联网行业的快速发展&#xff0c;越来越多的人选择从事程序员这个职业。然而&#xff0c;长时间的工作和高强度的压力容易导致程序员出现亚健康状况&#xff0c;如头发稀疏、视力下降、肥胖等问题。因此&#…...

CNN对 MNIST 数据库中的图像进行分类

加载 MNIST 数据库 MNIST 是机器学习领域最著名的数据集之一。 它有 70,000 张手写数字图像 - 下载非常简单 - 图像尺寸为 28x28 - 灰度图 from keras.datasets import mnist# 使用 Keras 导入MNIST 数据库 (X_train, y_train), (X_test, y_test) mnist.load_data()print(&…...

HarmonyOS开发工具简介

工具简介 更新时间: 2023-10-13 11:06 分享 添加收藏 说明 该文档匹配DevEco Studio 3.1.1 Release版本。 概述 HUAWEI DevEco Studio&#xff08;获取工具请单击链接下载&#xff0c;以下简称DevEco Studio&#xff09;是基于IntelliJ IDEA Community开源版本打造&#xff0c…...

大量索引场景下 Easysearch 和 Elasticsearch 的吞吐量差异

最近有客户在使用 Elasticsearch 搜索服务时发现集群有掉节点&#xff0c;并且有 master 收集节点信息超时的日志&#xff0c;节点的负载也很高&#xff0c;不只是 data 节点&#xff0c;master 和协调节点的 cpu 使用率都很高&#xff0c;看现象集群似乎遇到了性能瓶颈。 查看…...

东明石化集团领导团队参访震坤行工业超市

东明石化集团领导团队参访震坤行工业超市 10月16日&#xff0c;山东东明石化集团&#xff08;以下简称东明石化&#xff09;总裁李治先生一行带队来访参观交流震坤行&#xff0c;与震坤行工业超市董事长兼CEO陈龙、销售负责团队开展座谈。期间&#xff0c;双方就企业数字化转型…...

Java常见的面试题(很基础那种)

这里介绍一下,一些比较基础的Java面试题,比较适合应届生、实习生这些朋友。因为对于刚出来工作的Java工程师,很多企业都偏向招一些基础比较好的苗子回来培养。所以啊,在校的朋友们,一定要在读书期间,多做项目,如果没有实际的项目,可以在github找一些案例来做参考,先模…...

MySQL处理并发访问和高负载的关键技术和策略

我深知在数据库管理中处理并发访问和高负载的重要性。在这篇文章中&#xff0c;我将探讨MySQL处理并发访问和高负载的关键技术和策略&#xff0c;以帮助读者更好地优化数据库性能。 图片来源&#xff1a;MySQL处理并发访问和高负载的关键技术和策略 MySQL数据库在处理并发访问…...

软件测试jmeter基本使用

1安装与配置 1.jdk下载 下载地址&#xff1a;https://www.oracle.com/java/technologies/downloads/#jdk18-windows&#xff08;压缩包中会给&#xff09; 2.jmeter下载 Apache JMeter - Download Apache JMeter&#xff08;压缩包中有&#xff09; 3.操作教学 打开软件后新…...

一文讲透Python函数中的局部变量和全局变量

变量的作用域就是变量能够发挥作用的区域&#xff0c;超出既定区域后就无法发挥作用。根据变量的作用域可以将变量分为局部变量和全局变量。 1.局部变量 局部变量是在函数内部定义并使用的变量&#xff0c;也就是说只有在函数内部&#xff0c;在函数运行时才会有效&#xff0…...

【LeetCode】每日一题 2023_11_23 HTML 实体解析器(调库/打工)

文章目录 刷题前唠嗑题目&#xff1a;HTML 实体解析器题目描述代码与解题思路 结语 刷题前唠嗑 题目&#xff1a;HTML 实体解析器 题目链接&#xff1a;1410. HTML 实体解析器 题目描述 代码与解题思路 func entityParser(s string) (ans string) {return strings.NewRepla…...

Flask SocketIO 实现动态绘图

Flask-SocketIO 是基于 Flask 的一个扩展&#xff0c;用于简化在 Flask 应用中集成 WebSocket 功能。WebSocket 是一种在客户端和服务器之间实现实时双向通信的协议&#xff0c;常用于实现实时性要求较高的应用&#xff0c;如聊天应用、实时通知等&#xff0c;使得开发者可以更…...

软著项目推荐 深度学习 植物识别算法系统

文章目录 0 前言2 相关技术2.1 VGG-Net模型2.2 VGG-Net在植物识别的优势(1) 卷积核&#xff0c;池化核大小固定(2) 特征提取更全面(3) 网络训练误差收敛速度较快 3 VGG-Net的搭建3.1 Tornado简介(1) 优势(2) 关键代码 4 Inception V3 神经网络4.1 网络结构 5 开始训练5.1 数据集…...

自动驾驶HWP 功能规范

目 录 概述 1 目的 1范围 1术语及缩写 1设计与实验标准 1 设计标准 2设计标准执行优先顺序 2功能规范 Specification 4 功能描述 Functional Description 4 工作条件与应用范围 Application Scope 4道路交通 4天气与光线 4传感器方案及需求 5 驾驶员状态监控系统 5前视摄像…...

Ubuntu 环境下 NFS 服务安装及配置使用

需求&#xff1a;公司内部有多台物理服务器&#xff0c;需要A服务器上的文件让B服务器访问&#xff0c;也就是两台服务器共享文件&#xff0c;当然也可以对A服务器上的文件做权限管理&#xff0c;让B服务器只读或者可读可写 1、NFS 介绍 NFS 是 Network FileSystem 的缩写&…...

vue.js如何根据后台返回来的图片url进行图片下载

原创/朱季谦 最近在做一个前端vue.js对接的功能模块时&#xff0c;需要实现一个下载图片的功能&#xff0c;后台返回来的是一串图片url&#xff0c;试了很多种方法&#xff0c;发现点击下载时出来的效果&#xff0c;都是跳到一个新的图片网页&#xff0c;后来经过一番琢磨&…...

获取WordPress分类链接

CMS模板主题首页多以分类列表的形式展示内容&#xff0c;一般需要在适当位置添加某分类归档页面链接的按钮&#xff0c;下面的代码可以帮你实现。 代码一、通过分类别名获取Wordpress分类链接&#xff1a; <?php $catget_category_by_slug(‘wordpress’); $cat_linksget_…...

<Linux>(极简关键、省时省力)《Linux操作系统原理分析之Linux 进程管理 5》(9)

《Linux操作系统原理分析之Linux 进程管理 5》&#xff08;9&#xff09; 4 Linux 进程管理4.5 Linux 信号4.5.1 信号的作用和种类1.信号机制2.信号种类 4.5.2 信号的处理4.5.3 信号处理函数1&#xff0e;数据结构2&#xff0e; 处理函数 signal3&#xff0e;程序例 4 Linux 进…...

Anthropic推出Claude 2.1聊天机器人;使用AI工具写作:挑战与策略

&#x1f989; AI新闻 &#x1f680; Anthropic推出Claude 2.1聊天机器人&#xff0c;支持20万个Token输入和提高准确度 摘要&#xff1a;Anthropic推出了Claude 2.1聊天机器人及对应的AI模型&#xff0c;支持输入多达20万个Token&#xff0c;并在准确度上有所改善。Claude已…...

多模态2025:技术路线“神仙打架”,视频生成冲上云霄

文&#xff5c;魏琳华 编&#xff5c;王一粟 一场大会&#xff0c;聚集了中国多模态大模型的“半壁江山”。 智源大会2025为期两天的论坛中&#xff0c;汇集了学界、创业公司和大厂等三方的热门选手&#xff0c;关于多模态的集中讨论达到了前所未有的热度。其中&#xff0c;…...

使用VSCode开发Django指南

使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架&#xff0c;专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用&#xff0c;其中包含三个使用通用基本模板的页面。在此…...

超短脉冲激光自聚焦效应

前言与目录 强激光引起自聚焦效应机理 超短脉冲激光在脆性材料内部加工时引起的自聚焦效应&#xff0c;这是一种非线性光学现象&#xff0c;主要涉及光学克尔效应和材料的非线性光学特性。 自聚焦效应可以产生局部的强光场&#xff0c;对材料产生非线性响应&#xff0c;可能…...

微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】

微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来&#xff0c;Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...

k8s从入门到放弃之Ingress七层负载

k8s从入门到放弃之Ingress七层负载 在Kubernetes&#xff08;简称K8s&#xff09;中&#xff0c;Ingress是一个API对象&#xff0c;它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress&#xff0c;你可…...

Linux简单的操作

ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...

MySQL 8.0 OCP 英文题库解析(十三)

Oracle 为庆祝 MySQL 30 周年&#xff0c;截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始&#xff0c;将英文题库免费公布出来&#xff0c;并进行解析&#xff0c;帮助大家在一个月之内轻松通过OCP认证。 本期公布试题111~120 试题1…...

零基础设计模式——行为型模式 - 责任链模式

第四部分&#xff1a;行为型模式 - 责任链模式 (Chain of Responsibility Pattern) 欢迎来到行为型模式的学习&#xff01;行为型模式关注对象之间的职责分配、算法封装和对象间的交互。我们将学习的第一个行为型模式是责任链模式。 核心思想&#xff1a;使多个对象都有机会处…...

使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台

🎯 使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台 📌 项目背景 随着大语言模型(LLM)的广泛应用,开发者常面临多个挑战: 各大模型(OpenAI、Claude、Gemini、Ollama)接口风格不统一;缺乏一个统一平台进行模型调用与测试;本地模型 Ollama 的集成与前…...

Android第十三次面试总结(四大 组件基础)

Activity生命周期和四大启动模式详解 一、Activity 生命周期 Activity 的生命周期由一系列回调方法组成&#xff0c;用于管理其创建、可见性、焦点和销毁过程。以下是核心方法及其调用时机&#xff1a; ​onCreate()​​ ​调用时机​&#xff1a;Activity 首次创建时调用。​…...