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

【MMKV】HarmonyOS中的优秀轻量化存储方式

MMKV

引言

在移动应用开发的世界里,数据存储和管理是至关重要的一环。随着技术的不断进步,开发者们对于高性能、轻量级、易用的数据存储解决方案的需求日益增长。MMKV(Memory Mapped Key-Value)正是这样一个开源的高性能key-value存储框架,它以其独特的优势在移动应用开发领域中占据了一席之地。

MMKV的出现,为开发者们提供了一个全新的选择。它不仅具备高性能、轻量级、易用性等特点,还支持多种数据类型,适用于Android、iOS以及HarmonyOS平台。无论是存储用户配置信息、缓存数据,还是在多进程环境下的数据共享,MMKV都能发挥出其卓越的性能优势。

然而,MMKV并非完美无缺。它的功能相对简单,不支持复杂的查询和分析操作,也不支持跨进程共享数据和网络同步。这就要求开发者在使用MMKV时,需要根据具体的应用场景和需求,权衡其优势和局限性,选择最合适的存储方式。

在接下来的内容中,我们将深入探讨MMKV的工作原理、安装方法、实际应用以及一些高级特性,帮助您更好地理解和使用这个强大的存储框架。

概述

MMKV(Memory Mapped Key-Value)是一个开源的高性能key-value存储框架,主要用于移动端应用的数据存储和管理。它具有轻量级、高性能、易用性等特点,适用于Android和iOS以及HarmonyOS平台。MMKV的特点包括:

  1. 高性能:MMKV 使用 mmap 使内存与文件保持同步,使用 protobuf 对值进行编码/解码,从而充分利用本机平台实现最佳性能。
    • 多进程并发:MMKV 支持进程间并发读读和读写访问。
  2. 轻量级
    • 少量文件:MMKV 包含进程锁、编码/解码辅助程序和 mmap 逻辑,仅此而已。它真的很整洁。
    • 大约 600K 的二进制大小:MMKV 在应用程序大小上为每个架构增加大约 600K,而压缩后 (HAR/HAP) 则少得多。
  3. 易用性:提供了简洁的API,方便开发者进行数据的读写操作,您可以随心所欲地使用 MMKV。所有更改都会立即保存,不需要,不需要调用。sync``flush
  4. 支持多种数据类型:可以存储基本数据类型、字符串、字节数组等数据。

优势

  1. 高性能:MMKV在性能上有很大优势,读写速度快,适合大规模数据存储和高并发访问。
  2. 内存映射:MMKV使用内存映射技术,可以直接将数据映射到内存中,提高了读写效率。
  3. 跨平台:MMKV支持Android和iOS平台,且提供了相似的API,方便开发者在不同平台上使用。

缺点

  1. 功能相对简单:相比较其他一些存储方案,MMKV的功能相对简单,不支持复杂的查询和分析操作。
  2. 不支持跨进程:MMKV不支持跨进程共享数据,这在一些场景下可能会有限制。
  3. 不支持网络同步:MMKV不支持网络同步,需要开发者自行处理数据同步的问题。

工作原理

MMKV的核心原理是内存映射。内存映射文件是一种将文件或磁盘块映射到内存的技术,使得读写文件就像读写内存一样。MMKV使用了mmap函数来实现内存映射,该函数是Linux提供的一种应用级内存映射工具。通过内存映射,MMKV可以大大提高读写性能,同时减少了内存拷贝和上下文切换的开销。

开始

安装

  1. 通过 OHPM(推荐):
  • 这是将 MMKV 添加到项目中的最快、最推荐的方法。
ohpm install @tencent/mmkv

或者手动将其添加到您的项目中

  • 将以下行添加到您的 app 模块上。oh-package.json5
"dependencies": {"@tencent/mmkv": "2.0.0",
}
  • 然后运行
ohpm install
  1. 通过来源

您可以按源集成 MMKV。

  • 查看 MMKV 源代码:

    git clone https://github.com/Tencent/MMKV.git
    

    注意

    • 您可以考虑将 MMKV 添加为 git 子模块。
    • 默认情况下,MMKV 以静态方式链接。如果您想要更小的二进制大小并且您知道自己在做什么,您可以编辑 MMKV 模块的文件,将行更改为 、 和 。libc++``build-profile.json5``"arguments": "-DOHOS_STL=c++_shared"``"cppFlags": "-DMMKV_STL_SHARED=1
    • 如果要直接访问 MMKV 的 C++ 接口,可以编辑 MMKV 模块的文件,将行改为 .请注意,这将稍微增加二进制文件的大小。build-profile.json5``"cppFlags": "…… -fvisibility=default ……"
  • 将以下行添加到您的 app 模块上。oh-package.json5

    "dependencies": {"@tencent/mmkv": "file:path/to/mmkv/OpenHarmony/MMKV",
    }
    
  • 然后运行

    ohpm install
    
通过预构建的 HAR(不推荐):

您可以通过预构建的 HAR 集成 MMKV。

  • 查看 MMKV 源代码:

    git clone https://github.com/Tencent/MMKV.git
    
  • 在 中打开 MMKV 项目,打开 Product 窗口,然后选择 Build Mode 到 “release”;选择 module,在菜单中选择 -> ,将构建结果作为 “MMKV.har” 导出到您的项目文件夹。path/to/mmkv/OpenHarmony``MMKV``Build``Make Module 'MMKV'

    • 您可以考虑将 MMKV 添加为 git 子模块。
    • 默认情况下,MMKV 以静态方式链接。如果您想要更小的二进制大小并且您知道自己在做什么,您可以编辑 MMKV 模块的文件,将行更改为 、 和 。libc++``build-profile.json5``"arguments": "-DOHOS_STL=c++_shared"``"cppFlags": "-DMMKV_STL_SHARED=1
    • 如果要直接访问 MMKV 的 C++ 接口,可以编辑 MMKV 模块的文件,将行改为 .请注意,这将稍微增加二进制文件的大小。build-profile.json5``"cppFlags": "…… -fvisibility=default ……"
  • 将以下行添加到您的 app 模块上。oh-package.json5

    "dependencies": {"@tencent/mmkv": "file:path/to/MMKV.har",
    }
    
  • 然后运行

    ohpm install
    

实际应用

MMKV适用于移动应用开发中的各种场景,如替代Preferences存储用户配置信息、缓存数据等。在实际应用中,开发者需要根据具体场景和需求来选择合适的存储方式,并结合MMKV的特点来优化应用的性能和稳定性。

通过 OHPM 安装:

ohpm install @tencent/mmkv

设置

您可以随心所欲地使用 MMKV。所有更改都会立即保存,不需要,无需调用。
在 App 启动时设置 MMKV,比如您的函数,添加以下几行:sync``apply``EntryAbility.onCreate()

import { MMKV } from '@tencent/mmkv';export default class EntryAbility extends UIAbility {onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {let appCtx = this.context.getApplicationContext();let mmkvRootDir = MMKV.initialize(appCtx);console.info('mmkv rootDir: ', mmkvRootDir);……}
  • MMKV 有一个全局实例,可以直接使用:

    import { MMKV } from '@tencent/mmkv';let mmkv = MMKV.defaultMMKV();
    mmkv.encodeBool('bool', true);
    console.info('bool = ', mmkv.decodeBool('bool'));mmkv.encodeInt32('int32', Math.pow(2, 31) - 1);
    console.info('max int32 = ', mmkv.decodeInt32('int32'));mmkv.encodeInt64('int', BigInt(2**63) - BigInt(1));
    console.info('max int64 = ', mmkv.decodeInt64('int'));let str: string = 'Hello OpenHarmony from MMKV';
    mmkv.encodeString('string', str);
    console.info('string = ', mmkv.decodeString('string'));
    
  • 删除和查询

    mmkv.removeValueForKey('bool');
    console.info('contains "bool"', mmkv.containsKey('bool'));mmkv.removeValuesForKeys(['int32', 'int']);
    console.info('all keys: ', mmkv.allKeys().join());
    

    如果不同的 module/logic 需要隔离存储,也可以单独创建自己的 MMKV 实例:

    var mmkv = MMKV.mmkvWithID('test');
    mmkv.encodeBool('bool', true);
    console.info('bool = ', mmkv.decodeBool('bool'));
    

    如果需要多进程访问,可以在 MMKV 初始化时设置:MMKV.MULTI_PROCESS_MODE

    var mmkv = MMKV.mmkvWithID('test-multi-process', MMKV.MULTI_PROCESS_MODE);
    mmkv.encodeBool('bool', true);
    console.info('bool = ', mmkv.decodeBool('bool'));
    

支持的类型

  • 基元类型:

    boolean, number, bigint, string

  • 类别和收藏:

    boolean[], number[], string[], ArrayBuffer

  • 自定义类:
    我们不直接支持自定义类,因为 OHOS 中没有替代类。您可以先编码/解码为 JSON。或者使用您喜欢的任何编码库,例如 protobuf。Parcel

    let user = {username: 'dummy_user',age: 23
    }// 将对象序列化为一个JSON字符串。
    mmkv.encodeString('user', JSON.stringify(user))// 将JSON字符串反序列化为对象。
    let jsonUser = mmkv.decodeString('user') // { 'username': 'dummy_user', 'age': 23 }
    let userObject = JSON.parse(jsonUser)
    

日志

  • 默认情况下,MMKV 将 log 打印到 hilog 中,这不方便诊断在线问题。 您可以在 MMKV 的本机接口上设置 MMKV 日志重定向。 查看如何在 C++ 上执行此操作。 由于 NAPI 运行时的当前限制,我们无法有效地将日志重定向到 JavaScript 端。

  • 您可以在初始化时一劳永逸地关闭 MMKV 的日志记录(我们强烈建议不要这样做)。

    import { MMKV, MMKVLogLevel } from '@tencent/mmkv';MMKV.initialize(appCtx, MMKVLogLevel.None);
    

加密

  • 默认情况下,MMKV 将所有键值以纯文本形式存储在文件中,依靠 Android/iOS 的沙盒来确保文件已加密。如果您担心信息泄露,您可以选择加密 MMKV。

    let encryptKey = 'MyEncryptKey';
    let mmkv = MMKV.mmkvWithID('test-encryption', MMKV.SINGLE_PROCESS_MODE, encryptKey);
    
  • 您可以稍后根据需要更改加密密钥。您还可以将现有 MMKV 实例从加密更改为未加密,反之亦然。

    // 未加密的 MMKV 实例
    let mmkv = MMKV.mmkvWithID('test-encryption');// 从未加密更改为加密
    mmkv.reKey('Key_seq_1');// 更改加密密钥
    mmkv.reKey('Key_seq_2');// 从加密更改为未加密
    kmmkv.reKey();
    

自定义位置

  • 默认情况下,MMKV 将文件存储在 .你可以在 App 启动时自定义 MMKV 的根目录$(FilesDir)/mmkv/

    let appCtx = this.context.getApplicationContext();
    let rootDir = appCtx.filesDir + '/mmkv_2';
    let cacheDir = appCtx.cacheDir;
    MMKV.initializeWithPath(rootDir, cacheDir);
    
  • 您甚至可以自定义任何 MMKV 实例的位置:

    let appCtx = this.context.getApplicationContext();
    let rootDir = appCtx.filesDir + '/mmkv_3';
    var mmkv = MMKV.mmkvWithID('testCustomDir', MMKV.SINGLE_PROCESS_MODE, null, rootDir);
    

    注意:建议将 MMKV 文件存储在应用的沙盒路径不要将它们存储在外部存储设备(又名 SD 卡)上。

原生缓冲区

  • 通常,当 or 值从 MMKV 获取时,会有一个内存从 **native 复制到 JSVM。**如果该值立即传递给另一个本机库 (NAPI),则会发生另一次从 JSVM 到本机的内存复制。如果该值的大小很大,则整个过程会浪费太多。Native Buffer 来了。
    Native Buffer 是用 native 创建的内存缓冲区,包装方式与 JavaScript 一样,可以透明地传递给另一个 native 库。此过程节省了向JSVM复制的内存。示例代码:string``ArrayBuffer``NativeBuffer

    let sizeNeeded = mmkv.getValueSize('bytes', true);
    let nativeBuffer = MMKV.createNativeBuffer(sizeNeeded);
    if (nativeBuffer != null) {let size = mmkv.writeValueToNativeBuffer('bytes', nativeBuffer);console.info('NativeBuffer: size Needed = ', sizeNeeded, ',  written size = ', size);// 将 nativeBuffer 传递给另一个原生库// ...// 完成后销毁MMKV.destroyNativeBuffer(nativeBuffer);
    }
    

备份和恢复

  • 您可以使用MMKV的备份和恢复API将数据备份到其他地方,然后再恢复它们。

    let rootDir = ...;
    let backupRootDir = rootDir + '/mmkv_backup';
    // 备份 1 实例
    let ret = MMKV.backupOneToDirectory(mmapID, backupRootDir);
    // 备份所有实例
    let count = MMKV.backupAllToDirectory(backupRootDir);
    // 还原 1 个实例
    ret = MMKV.restoreOneMMKVFromDirectory(mmapID, backupRootDir);
    // 还原所有实例
    count = MMKV.restoreAllFromDirectory(backupRootDir);
    

自动过期

  • 您可以将 MMKV 升级为自动密钥过期。请注意,这是一项重大更改。升级到自动密钥过期后,该文件对于任何旧版本的 MMKV (<= v1.2.16) 都无效,无法正常运行。

  • 全局过期时间。最简单的方法是为整个文件中的所有键开启自动密钥过期。

    // 一天后过期
    mmkv.enableAutoKeyExpire(MMKV.ExpireInDay); // MMKV.ExpireInDay = 24 * 60 * 60
    

    或者,如果您愿意,可以启用自动密钥过期,而无需设置全局过期持续时间。在这种情况下,默认情况下每个密钥都不会过期。

    // 启用无全局持续时间的自动密钥过期
    mmkv.enableAutoKeyExpire(MMKV.ExpireNever); // MMKV.ExpireNever = 0
    
  • 个人到期日。您可以为密钥设置特殊的过期持续时间,无论文件是否具有全局持续时间。请注意,您必须先启用自动密钥过期

    // 启用持续时间为一小时的自动密钥过期
    mmkv.enableAutoKeyExpire(MMKV.ExpireInHour); // MMKV.ExpireInHour = 60 * 60// 设置一个具有文件全局过期持续时间的键,即 MMKV.ExpireInHour
    mmkv.encodeString('key_1', 'some value');// 设置一个 2 小时后过期的特殊密钥
    mmkv.encodeString('key_2', 'some value', 2 * 60 * 60);// 设置永不过期的特殊密钥
    mmkv.encodeString('key_3', 'some value', MMKV.ExpireNever);
    

    或者,如果您愿意,可以启用自动密钥过期,而无需设置全局过期持续时间。在这种情况下,默认情况下每个密钥都不会过期。

    // 启用无全局持续时间的自动密钥过期
    mmkv.enableAutoKeyExpire(MMKV.ExpireNever); // MMKV.ExpireNever = 0// 设置永不过期的密钥
    mmkv.encodeString('key_1', 'some value');// 设置一个 1 小时后过期的特殊密钥
    mmkv.encodeString('key_2', 'some value', MMKV.ExpireInHour);
    
  • 过期持续时间以秒为单位。为方便起见,MMKV 有一些预定义的持续时间。您可以使用您喜欢的任何其他持续时间。例如,一周后的过期时间为 。7 * 24 * 60 * 60

    static const int ExpireNever = 0;
    static const int ExpireInMinute = 60;
    static const int ExpireInHour = 60 * 60;
    static const int ExpireInDay = 24 * 60 * 60;
    static const int ExpireInMonth = 30 * 24 * 60 * 60;
    static const int ExpireInYear = 365 * 30 * 24 * 60 * 60;
    

相关文章:

【MMKV】HarmonyOS中的优秀轻量化存储方式

MMKV 引言 在移动应用开发的世界里&#xff0c;数据存储和管理是至关重要的一环。随着技术的不断进步&#xff0c;开发者们对于高性能、轻量级、易用的数据存储解决方案的需求日益增长。MMKV&#xff08;Memory Mapped Key-Value&#xff09;正是这样一个开源的高性能key-val…...

docker安装hadoop环境

一、使用docker搭建基础镜像 1、拉取centos系统镜像 # 我这里使用centos7为例子 docker pull centos:7 2、创建一个dockerfiler文件&#xff0c;用来构建自定义一个有ssh功能的centos镜像 # 基础镜像 FROM centos:7 # 作者 #MAINTAINER hadoop ADD Centos-7.repo /etc/yum.re…...

开源多媒体处理工具ffmpeg是什么?如何安装?使用ffmpeg将M3U8格式转换为MP4

目录 一、FFmpeg是什么二、安装FFmpeg&#xff08;windows&#xff09;三、将M3U8格式转换为MP4格式 一、FFmpeg是什么 FFmpeg是一款非常强大的开源多媒体处理工具&#xff0c;它几乎可以处理所有类型的视频、音频、字幕以及相关的元数据。 FFmpeg的主要用途包括但不限于&…...

算法刷题Day5: BM52 数组中只出现一次的两个数字

描述&#xff1a; 一个整型数组里除了两个数字只出现一次&#xff0c;其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。 要求&#xff1a;空间复杂度 O(1)&#xff0c;时间复杂度O(n)。 题目传送门 is here 思路&#xff1a; 方法一&#xff1a;最简单的思路就…...

55 基于单片机的方波频率可调

目录 一、主要功能 二、硬件资源 三、程序编程 四、实现现象 一、主要功能 采用STC89C52单片机最小系统&#xff0c;设计DAC0832、放大器、与示波器显示方波&#xff0c;四位数码管显示频率&#xff0c;两个按键可调。 二、硬件资源 基于KEIL5编写C代码&#xff0c;PROT…...

23.useUnload

在 Web 应用开发中,处理页面卸载(unload)事件是一个重要但常常被忽视的方面。无论是提醒用户保存未保存的更改,还是执行一些清理操作,都需要在用户即将离开页面时进行处理。useUnload 钩子提供了一种简洁的方式来在 React 组件中处理 beforeunload 事件,使得在用户试图关…...

linux环境搭建

1、**连接外网** ssh在192.168.4.x上运行sudo ip link set ens160 down ssh切换到192.168.3.x(外网ip)&#xff0c;运行sudo ip route add default via 192.168.2.1 dev ens192 onlink //连接外网 使用完外网后 ssh在192.168.3.x上运行sudo ip link set ens160 up ssh在1…...

《C++与生物医学的智能融合:医疗变革新引擎》

在当今科技飞速发展的时代&#xff0c;人工智能正以前所未有的深度和广度渗透到各个领域&#xff0c;为传统行业带来革新与突破。其中&#xff0c;将 C与生物学、医学等领域知识相结合&#xff0c;开发用于处理生物医学数据、辅助疾病诊断和治疗的人工智能应用&#xff0c;成为…...

Matlab 绘制雷达图像完全案例和官方教程(亲测)

首先上官方教程链接 polarplothttps://ww2.mathworks.cn/help/matlab/ref/polarplot.html 上实例 % 定义角度向量和径向向量 theta linspace(0, 2*pi, 5); r1 [1, 2, 1.5, 2.5, 1]; r2 [2, 1, 2.5, 1.5, 2];% 绘制两个雷达图 polarplot(theta, r1, r-, LineWidth, 2); hold …...

Lua的环境与热更

一、global_State,lua_State与G表 Lua支持多线程环境&#xff0c;使用 lua_State 结构来表示一个独立的 Lua 线程&#xff08;或协程&#xff09;。每个线程都需要一个独立的全局环境。而lua_State 中的l_G指针&#xff0c;指向一个global_State结构&#xff0c;这个就是我们常…...

HTML CSS JS基础考试题与答案

一、选择题&#xff08;2分/题&#xff09; 1&#xff0e;下面标签中&#xff0c;用来显示段落的标签是&#xff08; d &#xff09;。 A、<h1> B、<br /> C、<img /> D、<p> 2. 网页中的图片文件位于html文件的下一级文件夹img中&#xff0c;…...

若依解析(一)登录认证流程

JWTSpringSecurity 6.X 实现登录 JWT token只包含uuid ,token 解析uuid&#xff0c;然后某个常量加UUID 从Redis缓存查询用户信息 流程图如下 感谢若依&#xff0c;感谢开源&#xff0c;能有这么好系统供我学习。 设计数据库&#xff0c;部门表&#xff0c;用户表&#xff0c…...

Redis设计与实现第17章 -- 集群 总结1(节点 槽指派)

集群通过分片sharding来进行数据共享&#xff0c;并提供复制和故障转移功能。 17.1 节点 一个Redis集群通常由多个节点node组成&#xff0c;刚开始每个节点都是相互独立的&#xff0c;必须将各个独立的节点连接起来&#xff0c;才能构成一个包含多个节点的集群。通过CLUSTER …...

汽车控制软件下载移动管家手机控车一键启动app

移动管家手机控制汽车系统是一款实现车辆远程智能控制的应用程序‌。通过下载并安装特定的APP&#xff0c;用户可以轻松实现以下功能&#xff1a;‌远程启动与熄火‌&#xff1a;无论身处何地&#xff0c;只要有网络&#xff0c;即可远程启动或熄火车辆&#xff0c;提前预冷或预…...

推荐几个可以免费下载网站模板的资源站

推荐几个可以免费下载网站模板的资源站&#xff0c;上面有免费的wordpress模板和帝国CMS模板可以下载。 模板帝 Mobandi.com 模板帝是一个提供丰富网站模板资源的平台&#xff0c;旨在帮助用户快速构建和美化自己的网站。无论是个人博客、企业官网还是电子商务平台&#xff…...

H3C OSPF实验

实验拓扑 实验需求 按照图示配置 IP 地址按照图示分区域配置 OSPF &#xff0c;实现全网互通为了路由结构稳定&#xff0c;要求路由器使用环回口作为 Router-id&#xff0c;ABR 的环回口宣告进骨干区域 实验解法 一、配置IP地址 [R1]int l0 [R1-LoopBack0]ip add 1.1.1.1 32 […...

Vue框架开发一个简单的购物车(Vue.js)

让我们利用所学知识来开发一个简单的购物车 &#xff08;记得暴露属性和方法&#xff01;&#xff01;&#xff01;&#xff09; 首先来看一下最基本的一个html框架 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"&…...

Windows Terminal Solarized Dark 配色方案调整

起因 Widnows 10/11 下面自带的 Terminal 还是比较方便的&#xff0c;因为不需要安装额外的 Terminal 软件。 我喜欢 Solarized Dark 配色方案&#xff0c;虽然有人批评这个配色方案比较老&#xff0c;但我觉得它比较优雅&#xff0c;尤其对外这种眼神比较差的人&#xff0c;比…...

PyTorch张量运算与自动微分

PyTorch张量运算与自动微分 PyTorch由Facebook人工智能研究院于2017年推出&#xff0c;具有强大的GPU加速张量计算功能&#xff0c;并且能够自动进行微分计算&#xff0c;从而可以使用基于梯度的方法对模型参数进行优化&#xff0c;大部分研究人员、公司机构、数据比赛都使用P…...

【从零开始的LeetCode-算法】3264. K 次乘运算后的最终数组 I

给你一个整数数组 nums &#xff0c;一个整数 k 和一个整数 multiplier 。 你需要对 nums 执行 k 次操作&#xff0c;每次操作中&#xff1a; 找到 nums 中的 最小 值 x &#xff0c;如果存在多个最小值&#xff0c;选择最 前面 的一个。将 x 替换为 x * multiplier 。 请你…...

【Linux】gdb / cgdb 调试 + 进度条

&#x1f33b;个人主页&#xff1a;路飞雪吖~ &#x1f320;专栏&#xff1a;Linux 目录 一、Linux调试器-gdb &#x1f31f;开始使用 &#x1f320;小贴士&#xff1a; &#x1f31f;gdb指令 &#x1f320;小贴士&#xff1a; ✨watch 监视 ✨打条件断点 二、小程序----进…...

Jenkins Nginx Vue项目自动化部署

目录 一、环境准备 1.1 Jenkins搭建 1.2 NVM和Nodejs安装 1.3 Nginx安装 二、Jenkins配置 2.1 相关插件安装 2.2 全局工具安装 2.3 环境变量配置 2.4 邮箱配置&#xff08;构建后发送邮件&#xff09; 2.5 任务配置 三、Nginx配置 3.1 配置路由转发 四、部署项目 …...

视频汇聚平台Liveweb国标GB28181视频平台监控中心设计

在现代安防视频监控领域&#xff0c;Liveweb视频汇聚平台以其卓越的兼容性和灵活的拓展能力&#xff0c;为用户提供了一套全面的解决方案。该平台不仅能够实现视频的远程监控、录像、存储与回放等基础功能&#xff0c;还涵盖了视频转码、视频快照、告警、云台控制、语音对讲以及…...

文件比较和文件流

文件比较和文件流 一、文本比较工具 diff1.基本用法1.1输出格式 2.常用选项 二、文件流1.文件的打开模式2.文件流的分类ifstreamofstreamfstrem区别 3.文件流的函数1. 构造函数2. is_open 用于判断文件是否打开3. open4. getline5. close6. get()7. read8. write9. put10. gcou…...

【2024最新】基于Springboot+Vue的就业信息管理系统Lw+PPT

作者&#xff1a;计算机搬砖家 开发技术&#xff1a;SpringBoot、php、Python、小程序、SSM、Vue、MySQL、JSP、ElementUI等&#xff0c;“文末源码”。 专栏推荐&#xff1a;SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;Java精选实战项…...

PySide6 QSS(Qt Style Sheets) Reference: PySide6 QSS参考指南

Qt官网参考资料&#xff1a; QSS介绍&#xff1a; Styling the Widgets Application - Qt for Pythonhttps://doc.qt.io/qtforpython-6/tutorials/basictutorial/widgetstyling.html#tutorial-widgetstyling QSS 参考手册&#xff1a; Qt Style Sheets Reference | Qt Widge…...

【笔记】成为雍正

观古代历史&#xff0c;不过帝王一家一姓之家史 时间 1662年&#xff0c;田文镜出生。1672年&#xff0c;张廷玉出生。1674年&#xff0c;胤礽出生。1678年&#xff0c;胤禛出生。1679年&#xff0c;年羹尧出生。1680年&#xff0c;鄂尔泰出生。1700年&#xff0c;索额图被赐死…...

Codeforces Round 913 (Div. 3)

题目链接 B. YetnotherrokenKeoard 题意 输入 输出 思路 用两个栈分别维护小写字母下标和大写字母下标&#xff0c;用一个vis数组标记字母是否删除 示例代码 void solve() {string s;cin >> s;int n s.size();vector<bool> vis(n, false);stack<int>sk…...

斐波那契数

C语言实现斐波那契数列的多种方法_斐波那契数列c语言-CSDN博客 题目描述 斐波那契数列为&#xff1a;1,1,2,3,5,8,13.....&#xff0c;常规递推公式f(n)f(n-1)f(n-2); 输入描述 输入一个整数n(0<n<50),为多组数据。 输出描述 输出第n个斐波那契数 样例输入 1 2 4样例输出…...

Redis高阶集群搭建+集群读写

问题 容量不够&#xff0c;redis 如何进行扩容&#xff1f;并发写操作&#xff0c; redis 如何分摊&#xff1f;另外&#xff0c;主从模式&#xff0c;薪火相传模式&#xff0c;主机宕机&#xff0c;导致 ip 地址发生变化&#xff0c;应用程序中配置需要修改对应的主机地址、端…...

珠海做网站开发/优化大师官网入口

目录&#xff1a;导读 引言 一、Web 端测试和 App 端测试有何不同? 二、App是如何测试的&#xff1f; 三、app闪退的可能原因&#xff1f; 四、给你一个登录页面,你要如何测试&#xff1f; 五、测试过程中遇到app出现crash或者ANR&#xff0c;你会怎么处理&#xff1f; …...

徐州市城乡和城乡建设厅网站首页/海外引流推广平台

相对于 SVN 默认的 diff 工具&#xff0c;我更习惯于用 beyond compare 做差异对比。通过更改 svn 的配置文件&#xff0c;即可将 beyond compare 作为 svn diff 的默认工具。 安装了 svn 之后&#xff0c;会在 home 目录下生成一个名为 .subversion 的隐藏目录。 首先&#…...

安陆做网站公司/域名查询网站

Python之建模规划篇--非线性规划基本介绍线性规划与非线性规划的区别非线性规划的Matlab解法Python 解决非线性规划1、等式约束下的拉格朗日乘子法2、Python实现对带约束的非线性规划求解Python编程实现求解python使用SciPy库实现求解问题结果对比样例1样例2基本介绍 如果目标…...

金华免费模板建站/重庆人力资源和社会保障网

新闻营销是企业营销方式中最重要的一种&#xff0c;新闻营销成功的关键除了稿件撰写之外&#xff0c;新闻稿件发布也至关重要&#xff0c;有时候企业辛辛苦苦写了新闻稿&#xff0c;发布效果却不明显&#xff0c;究其原因是什么呢&#xff1f; 一、网络媒体关系构建建立网络媒…...

重庆沙坪坝做网站/优化网站软文

10月17日&#xff0c;“圆明园研究与保护2021国际学术研讨会暨第二届圆明园研究高校联盟成果展”在圆明园举行。本次活动由圆明园研究高校联盟和北京交通大学共同主办&#xff0c;金一文化作为贵金属文创唯一合作单位参与了本次活动。 研讨会设“圆明园历史文化研究”“圆明园…...

电子名片制作app/谷歌seo营销

看什么看&#xff0c;快点蓝字关注我&#xff01;你打算脱离IT运营吗&#xff1f;你敢这样想、这样做吗&#xff1f;现在&#xff0c;云服务的出现可以让你多年的愿望变成真。对于大多数的企业来说&#xff0c;IT只是支持其业务创新与发展的工具&#xff0c;而非核心业务。但实…...