Android磁盘占用优化全解析:从监控到治理的存储效率革命

引言

随着移动应用功能的复杂化,磁盘占用问题日益突出。据统计,国内头部应用的平均安装包大小已超100MB,运行时缓存、日志、图片等数据更可能使磁盘占用突破GB级。过度的磁盘消耗不仅影响用户设备空间,还可能触发系统的“应用数据过多”警告,导致用户卸载。本文将从磁盘监控、存储目录解析、优化策略三个维度展开,结合Android系统API与实际代码示例,系统性讲解磁盘占用的全流程优化。

一、磁盘占用监控:从开发到线上的精准定位

优化的前提是精准监控。本节将介绍开发期工具、系统API以及线上监控方案,帮助开发者快速定位“磁盘膨胀”的根源。

1.1 开发期工具:Android Studio 存储分析

Android Studio提供了Storage Profiler(存储分析器)和Device File Explorer(设备文件浏览器),可直观查看应用的文件、数据库、共享首选项等存储内容的大小和分布。

(1)Storage Profiler实战

通过Storage Profiler可实时监控:

  • 应用内部存储(/data/data/<包名>)的文件、数据库、SP大小;
  • 外部存储(/storage/emulated/0/Android/data/<包名>)的缓存、图片等数据;
  • 随时间变化的存储增长曲线(见图1)。

操作步骤

  1. 连接设备,打开Android Studio的Profiler面板;
  2. 选择目标应用,点击Storage标签;
  3. 触发存储操作(如加载图片、保存日志),观察各分类的大小变化;
  4. 点击具体文件类型(如Files),查看详细文件列表及路径。
(2)Device File Explorer深度排查

通过Device File Explorer可直接访问设备文件系统,手动查看文件内容并删除测试数据。

注意:需通过adb root获取root权限(模拟器默认开启),否则无法访问内部存储的私有目录。

1.2 系统API:代码级存储监控

通过Android系统提供的StatFsContextFile类,可在代码中主动获取存储信息。

(1)获取存储容量(总空间/可用空间)

使用StatFs(API 18+)获取文件系统的容量信息,支持内部存储和外部存储。

示例:计算内部存储可用空间

fun getInternalStorageFreeSpace(): Long {val dataDir = Environment.getDataDirectory() // 内部存储根目录(/data)val statFs = StatFs(dataDir.path)val blockSize = statFs.blockSizeLong // 块大小(字节)val availableBlocks = statFs.availableBlocksLong // 可用块数return availableBlocks * blockSize
}// 外部存储(SD卡)可用空间(需权限android.permission.READ_EXTERNAL_STORAGE)
fun getExternalStorageFreeSpace(): Long {val externalDir = Environment.getExternalStorageDirectory() // 外部存储根目录(/storage/emulated/0)val statFs = StatFs(externalDir.path)val blockSize = statFs.blockSizeLongval availableBlocks = statFs.availableBlocksLongreturn availableBlocks * blockSize
}
(2)统计应用目录大小

遍历应用专属目录(如filescache),递归计算所有文件的总大小。

示例:计算应用缓存目录大小

fun getCacheDirSize(context: Context): Long {val cacheDir = context.cacheDir // 内部缓存目录(/data/data/<包名>/cache)return calculateDirSize(cacheDir)
}private fun calculateDirSize(dir: File): Long {if (!dir.exists()) return 0Lvar totalSize = 0Lval files = dir.listFiles()if (files != null) {for (file in files) {totalSize += if (file.isDirectory) {calculateDirSize(file) // 递归子目录} else {file.length() // 文件大小(字节)}}}return totalSize
}

1.3 线上监控:用户真实场景数据上报

开发期工具适合调试,线上环境需通过日志上报收集用户的存储使用数据,重点监控:

  • 应用总存储大小(内部+外部);
  • 各子目录(如cachefiles/image)的大小占比;
  • 异常大文件(如单个文件超过100MB)。

示例:线上存储监控上报

class StorageMonitor {fun reportStorageUsage(context: Context) {val internalCacheSize = getCacheDirSize(context)val externalCacheSize = getExternalCacheDirSize(context) // 外部缓存目录(/storage/emulated/0/Android/data/<包名>/cache)val filesDirSize = calculateDirSize(context.filesDir)val databasesSize = calculateDirSize(context.getDatabasePath("app.db").parentFile) // 数据库目录// 上报到后台(使用埋点SDK)Analytics.report("storage_usage", mapOf("internal_cache" to internalCacheSize,"external_cache" to externalCacheSize,"files_dir" to filesDirSize,"databases" to databasesSize))}private fun getExternalCacheDirSize(context: Context): Long {val externalCacheDir = context.externalCacheDir // Android 4.4+无需权限return externalCacheDir?.let { calculateDirSize(it) } ?: 0L}
}

二、存储目录解析:理解Android的存储架构

Android的存储分为内部存储外部存储,不同目录的生命周期、访问权限和优化策略差异显著。

2.1 内部存储(Internal Storage)

内部存储是应用私有的存储空间,路径为/data/data/<包名>/,仅应用自身可访问(需root权限除外)。

核心子目录:
目录路径特点优化方向
files/data/data/<包名>/files长期存储数据(如用户配置),应用卸载后删除清理过期数据
cache/data/data/<包名>/cache临时缓存(如网络请求临时文件),系统可能自动清理限制最大容量
databases/data/data/<包名>/databasesSQLite数据库存储目录优化表结构、删除冗余数据
shared_prefs/data/data/<包名>/shared_prefsSharedPreferences存储的XML文件(如用户设置)合并SP文件、减少冗余键值

2.2 外部存储(External Storage)

外部存储包括设备内置的大容量存储(如手机存储)或可移除的SD卡,路径为/storage/emulated/0/(虚拟路径)。根据Android版本不同,访问权限差异较大:

(1)应用专属目录(App-specific Storage)

路径为/storage/emulated/0/Android/data/<包名>/,应用卸载后自动删除,无需READ_EXTERNAL_STORAGE权限(Android 4.4+)。

核心子目录

  • files:长期存储(如用户下载的文件);
  • cache:临时缓存(如图片缓存);
  • obb:OBB扩展文件(如游戏资源包)。

示例:获取外部专属目录

// 外部files目录(如/storage/emulated/0/Android/data/<包名>/files)
val externalFilesDir = context.getExternalFilesDir(null)// 外部图片子目录(自动创建)
val externalImageDir = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES)
(2)公共目录(Public Storage)

路径为/storage/emulated/0/DCIM/storage/emulated/0/Download等,所有应用可访问,需READ_EXTERNAL_STORAGEWRITE_EXTERNAL_STORAGE权限(Android 10+需通过MediaStore访问)。

注意:公共目录的数据在应用卸载后不会删除,需谨慎使用,仅用于用户主动保存的内容(如用户导出的图片)。

2.3 不同存储目录的选择策略

场景推荐目录原因
敏感数据(如用户Token)内部存储files私有性强,外部无法访问
临时缓存(如网络图片)内部/外部cache系统可自动清理,避免占用用户空间
用户生成内容(如导出图片)外部公共目录(DCIM用户可通过相册查看,卸载后保留

三、磁盘优化策略:从代码到架构的深度治理

通过监控定位高占用目录后,需针对具体场景制定优化策略。本节将结合常见存储场景,提供代码级解决方案。

3.1 缓存优化:限制容量与自动清理

缓存是磁盘占用的“重灾区”,需通过容量限制过期策略避免无限增长。

(1)内存缓存(LruCache)与磁盘缓存(DiskLruCache)结合
  • LruCache:内存缓存,限制最大条目数(如设备内存的1/8);
  • DiskLruCache:磁盘缓存,限制最大容量(如100MB),自动删除最久未使用(LRU)的文件。

示例:配置DiskLruCache

class ImageCache(context: Context) {private val diskCacheSize = 100 * 1024 * 1024 // 100MBprivate val diskCache: DiskLruCacheinit {val cacheDir = getDiskCacheDir(context, "image_cache")if (!cacheDir.exists()) cacheDir.mkdirs()diskCache = DiskLruCache.open(cacheDir, 1, // 每个key对应1个文件1, // 每个文件版本号diskCacheSize)}// 获取缓存目录(优先外部存储,否则内部)private fun getDiskCacheDir(context: Context, uniqueName: String): File {val externalCacheDir = context.externalCacheDirreturn if (externalCacheDir != null && externalCacheDir.canWrite()) {File(externalCacheDir, uniqueName)} else {File(context.cacheDir, uniqueName)}}// 缓存图片fun putImage(url: String, bitmap: Bitmap) {val key = hashKeyForDisk(url)val editor = diskCache.edit(key) ?: returntry {val outputStream = editor.newOutputStream(0)bitmap.compress(Bitmap.CompressFormat.WEBP, 80, outputStream)editor.commit()} finally {editor.abortUnlessCommitted()}}// 获取缓存图片fun getImage(url: String): Bitmap? {val key = hashKeyForDisk(url)val snapshot = diskCache.get(key) ?: return nullval inputStream = snapshot.getInputStream(0)return BitmapFactory.decodeStream(inputStream)}// URL转哈希键(避免特殊字符)private fun hashKeyForDisk(key: String): String {return try {val messageDigest = MessageDigest.getInstance("MD5")messageDigest.update(key.toByteArray())bytesToHex(messageDigest.digest())} catch (e: NoSuchAlgorithmException) {key.hashCode().toString()}}private fun bytesToHex(bytes: ByteArray): String {val hexString = StringBuilder()for (byte in bytes) {val hex = String.format("%02x", byte)hexString.append(hex)}return hexString.toString()}
}
(2)设置缓存过期时间

为缓存文件添加时间戳,定期清理过期数据(如超过7天的缓存)。

示例:自动清理过期缓存

fun cleanExpiredCache(cacheDir: File, maxAge: Long) {val currentTime = System.currentTimeMillis()val files = cacheDir.listFiles() ?: returnfor (file in files) {if (file.isDirectory) {cleanExpiredCache(file, maxAge) // 递归子目录} else {val lastModified = file.lastModified()if (currentTime - lastModified > maxAge) { // 超过最大年龄file.delete()}}}
}// 调用:清理7天前的缓存(7*24*3600*1000)
cleanExpiredCache(context.cacheDir, 7 * 24 * 3600 * 1000L)

3.2 大文件管理:压缩、分块与按需加载

图片、视频、日志等大文件是磁盘占用的主要来源,需通过压缩分块存储按需加载优化。

(1)图片压缩
  • 分辨率压缩:根据设备屏幕尺寸加载合适分辨率的图片(如1080P设备加载1080P图,而非4K图);
  • 质量压缩:调整JPEG/WebP的压缩质量(如列表图压缩至80%,详情页压缩至90%)。

示例:图片压缩工具类

object ImageCompressor {fun compress(bitmap: Bitmap, maxSize: Int = 200 * 1024): ByteArray {val outputStream = ByteArrayOutputStream()var quality = 100bitmap.compress(Bitmap.CompressFormat.JPEG, quality, outputStream)var byteArray = outputStream.toByteArray()// 循环压缩直到小于maxSize(200KB)while (byteArray.size > maxSize && quality > 10) {quality -= 10outputStream.reset()bitmap.compress(Bitmap.CompressFormat.JPEG, quality, outputStream)byteArray = outputStream.toByteArray()}return byteArray}
}
(2)日志分块存储

将大日志文件按时间或大小分块(如每天一个文件,每个文件不超过10MB),避免单个文件过大。

示例:分块日志写入

class ChunkedLogWriter(context: Context) {private val logDir = File(context.filesDir, "logs")private var currentFile: File? = nullprivate var currentSize = 0Lprivate val maxFileSize = 10 * 1024 * 1024 // 10MBinit {if (!logDir.exists()) logDir.mkdirs()}fun writeLog(log: String) {val currentTime = System.currentTimeMillis()val fileName = "log_${SimpleDateFormat("yyyyMMdd", Locale.CHINA).format(Date(currentTime))}.txt"val newFile = File(logDir, fileName)// 切换文件:新日期或当前文件超过最大大小if (currentFile == null || currentFile!!.name != fileName || currentSize > maxFileSize) {currentFile = newFilecurrentSize = newFile.length()}// 写入日志currentFile?.appendText("$log\n")currentSize += log.length + 1 // 换行符}
}
(3)按需加载与删除

仅在需要时下载大文件(如用户打开某页面时加载对应的资源包),使用后及时删除不再需要的文件。

示例:按需加载资源包

suspend fun loadResourcePack(packName: String) {val resourceDir = File(context.filesDir, "resources")val packFile = File(resourceDir, "$packName.zip")if (!packFile.exists()) {// 下载资源包(仅Wi-Fi时)if (isWifiConnected(context)) {val response = okHttpClient.newCall(Request.Builder().url("https://example.com/resources/$packName.zip").build()).execute()response.body?.byteStream()?.use { input ->FileOutputStream(packFile).use { output ->input.copyTo(output)}}} else {throw IOException("仅支持Wi-Fi下载资源包")}}// 使用资源包...// 使用后标记为可删除(如7天未使用则清理)packFile.setLastModified(System.currentTimeMillis())
}// 清理7天未使用的资源包
fun cleanUnusedResources() {val resourceDir = File(context.filesDir, "resources")val sevenDaysAgo = System.currentTimeMillis() - 7 * 24 * 3600 * 1000resourceDir.listFiles()?.forEach { file ->if (file.lastModified() < sevenDaysAgo) {file.delete()}}
}

3.3 数据库优化:减少冗余与索引优化

SQLite数据库的不合理使用(如冗余字段、未优化的查询)会导致磁盘占用激增。

(1)减少冗余数据
  • 字段精简:移除不再使用的字段;
  • 关联表设计:通过外键关联表,避免重复存储相同数据(如用户信息与订单信息分离)。

示例:优化用户-订单表结构

-- 优化前(冗余存储用户姓名)
CREATE TABLE orders (order_id INTEGER PRIMARY KEY,user_id INTEGER,user_name TEXT, -- 冗余字段amount REAL
);-- 优化后(通过user_id关联)
CREATE TABLE users (user_id INTEGER PRIMARY KEY,user_name TEXT
);CREATE TABLE orders (order_id INTEGER PRIMARY KEY,user_id INTEGER,amount REAL,FOREIGN KEY (user_id) REFERENCES users(user_id)
);
(2)使用WAL模式与自动 vacuum
  • WAL(Write-Ahead Logging):替代传统的回滚日志,减少磁盘IO,提升性能(默认开启);
  • 自动 vacuum:定期执行VACUUM命令,回收被删除数据占用的磁盘空间。

示例:配置SQLiteOpenHelper

class AppDatabaseHelper(context: Context) : SQLiteOpenHelper(context, "app.db", null, 1
) {override fun onCreate(db: SQLiteDatabase) {db.execSQL("CREATE TABLE users (user_id INTEGER PRIMARY KEY, name TEXT)")db.execSQL("CREATE TABLE orders (order_id INTEGER PRIMARY KEY, user_id INTEGER, amount REAL)")}override fun onConfigure(db: SQLiteDatabase) {super.onConfigure(db)db.enableWriteAheadLogging() // 启用WAL模式}fun vacuumDatabase() {writableDatabase.execSQL("VACUUM") // 手动触发清理}
}
(3)索引优化

合理使用索引可减少查询时间,但过多索引会增加磁盘占用。需权衡索引数量与查询效率。

示例:为高频查询字段添加索引

-- 为orders表的user_id添加索引(高频查询条件)
CREATE INDEX idx_orders_user_id ON orders(user_id);

3.4 临时文件与重复文件清理

临时文件(如拍照缓存、下载临时包)和重复文件(如用户多次下载同一资源)是磁盘的“隐形杀手”。

(1)临时文件自动清理
  • 生命周期绑定:临时文件的生命周期与对应操作绑定(如拍照后若用户取消,立即删除缓存);
  • 应用启动/退出时清理:在Application.onCreate()Activity.onDestroy()中清理临时目录。

示例:拍照临时文件清理

class CameraActivity : AppCompatActivity() {private var tempImageFile: File? = nullfun takePhoto() {tempImageFile = createTempImageFile() // 创建临时文件val photoUri = FileProvider.getUriForFile(this, "$packageName.fileprovider", tempImageFile!!)val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE).apply {putExtra(MediaStore.EXTRA_OUTPUT, photoUri)}startActivityForResult(intent, REQUEST_IMAGE_CAPTURE)}override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {super.onActivityResult(requestCode, resultCode, data)if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode != RESULT_OK) {// 用户取消,删除临时文件tempImageFile?.delete()}}private fun createTempImageFile(): File {val storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES)return File.createTempFile("JPEG_${System.currentTimeMillis()}_", ".jpg", storageDir)}
}
(2)重复文件检测

通过哈希值(如MD5、SHA-1)检测重复文件,仅保留一份。

示例:重复文件检测工具

fun findDuplicateFiles(dir: File): Map<String, List<File>> {val hashMap = mutableMapOf<String, MutableList<File>>()val files = dir.listFiles() ?: return hashMapfor (file in files) {if (file.isFile) {val hash = computeFileHash(file)hashMap.getOrPut(hash) { mutableListOf() }.add(file)}}// 过滤仅保留重复的文件(列表大小>1)return hashMap.filterValues { it.size > 1 }
}private fun computeFileHash(file: File): String {val messageDigest = MessageDigest.getInstance("SHA-256")FileInputStream(file).use { input ->val buffer = ByteArray(8192)var bytesRead: Intwhile (input.read(buffer).also { bytesRead = it } != -1) {messageDigest.update(buffer, 0, bytesRead)}}return bytesToHex(messageDigest.digest())
}

四、磁盘优化验证:从实验室到用户的效果评估

优化完成后,需通过实验室测试和用户场景模拟验证效果。

4.1 实验室测试工具

  • Android Studio Storage Profiler:对比优化前后各目录的大小变化;
  • adb命令:通过adb shell du -sh /data/data/<包名>查看应用总存储大小;
  • SQLite Browser:手动检查数据库文件大小,验证冗余数据清理效果。

4.2 用户场景模拟

通过模拟用户高频操作(如下载、拍照、缓存加载),观察磁盘占用的增长趋势:

# 模拟连续拍照(生成临时文件)
adb shell am start -n com.example.app/.CameraActivity
adb shell input keyevent KEYCODE_CAMERA# 模拟大量图片加载(触发缓存)
adb shell am start -n com.example.app/.ImageListActivity

五、总结

磁盘占用优化是一个“监控-分析-治理-验证”的闭环过程。核心策略包括:

  1. 缓存优化:限制容量、设置过期时间;
  2. 大文件管理:压缩、分块、按需加载;
  3. 数据库优化:减少冗余、索引优化;
  4. 临时文件清理:生命周期绑定、重复文件检测。

开发者需建立“开发期监控+线上上报”的双轨机制,持续迭代优化策略,在功能完整性与存储效率间找到最佳平衡。

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

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

相关文章

AJAX-让数据活起来(一):入门

目录 一、AJAX概念和axios使用 1.1 什么是AJAX ? 1.2 怎么用AJAX ? 1.3 axios使用 二、认识URL 2.1 什么是URL? 2.2 URL的组成 组成 协议 域名 资源路径 获取-新闻列表 三、URL查询参数 URL查询参数 axios - 查询参数 四、常用请求方法和数据提交 常用请求…

【C++篇】list模拟实现

实现接口&#xff1a; list的无参构造、n个val构造、拷贝构造 operator重载 实现迭代器 push_back() push_front() erase() insert() 头尾删 #pragma once #include<iostream> #include<assert.h> using namespace std;namespace liu {//定义list节点temp…

Go 语言范围循环变量重用问题与 VSCode 调试解决方法

文章目录 问题描述问题原因1. Go 1.21 及更早版本的范围循环行为2. Go 1.22 的改进3. VSCode 调试中的问题4. 命令行 dlv debug 的正确输出 三种解决方法1. 启用 Go 模块2. 优化 VSCode 调试配置3. 修改代码以确保兼容性4. 清理缓存5. 验证环境 验证结果结论 在 Go 编程中&…

快速创建 Vue 3 项目

安装 Node.js 和 Vue CL 安装 Node.js&#xff1a;访问 https://nodejs.org/ 下载并安装 LTS 版本。 安装完后&#xff0c;在终端检查版本&#xff1a; node -v npm -v安装 Vue CLI&#xff08;全局&#xff09;&#xff1a; npm install -g vue/cli创建 Vue 3 项目 vue cr…

java学习日志——Spring Security介绍

使用Spring Security要重写UserDetailsService的loadUserByUsername方法&#xff08;相当于自定了认证逻辑&#xff09;

【C++进阶篇】初识哈希

哈希表深度剖析&#xff1a;原理、冲突解决与C容器实战 一. 哈希1.1 哈希概念1.2 哈希思想1.3 常见的哈希函数1.3.1 直接定址法1.3.2 除留余数法1.3.3 乘法散列法&#xff08;了解&#xff09;1.3.4 平方取中法&#xff08;了解&#xff09; 1.4 哈希冲突1.4.1 冲突原因1.4.2 解…

单机Kafka配置ssl并在springboot使用

目录 SSL证书生成根证书生成服务端和客户端证书生成keystore.jks和truststore.jks辅助脚本单独生成truststore.jks 环境配置hosts文件kafka server.properties配置ssl 启动kafkakafka基础操作springboot集成准备工作需要配置的文件开始消费 SSL证书 证书主要包含两大类&#x…

PCB设计教程【入门篇】——电路分析基础-元件数据手册

前言 本教程基于B站Expert电子实验室的PCB设计教学的整理&#xff0c;为个人学习记录&#xff0c;旨在帮助PCB设计新手入门。所有内容仅作学习交流使用&#xff0c;无任何商业目的。若涉及侵权&#xff0c;请随时联系&#xff0c;将会立即处理 目录 前言 一、数据手册的重要…

Vue2实现Office文档(docx、xlsx、pdf)在线预览

&#x1f31f; 前言 欢迎来到我的技术小宇宙&#xff01;&#x1f30c; 这里不仅是我记录技术点滴的后花园&#xff0c;也是我分享学习心得和项目经验的乐园。&#x1f4da; 无论你是技术小白还是资深大牛&#xff0c;这里总有一些内容能触动你的好奇心。&#x1f50d; &#x…

【辰辉创聚生物】JAK-STAT信号通路相关蛋白:细胞信号传导的核心枢纽

在细胞间复杂的信号传递网络中&#xff0c;Janus 激酶 - 信号转导和转录激活因子&#xff08;JAK-STAT&#xff09;信号通路犹如一条高速信息公路&#xff0c;承担着传递细胞外信号、调控基因表达的重要使命。JAK-STAT 信号通路相关蛋白作为这条信息公路上的 “关键节点” 和 “…

OceanBase数据库从入门到精通(运维监控篇)

文章目录 一、OceanBase 运维监控体系概述二、OceanBase 系统表与元数据查询2.1 元数据查询基础2.2 核心系统表详解2.3 分区元数据查询实战三、OceanBase 性能监控SQL详解3.1 关键性能指标监控3.2 SQL性能分析实战四、OceanBase 空间使用监控4.1 表空间监控体系4.2 空间使用趋势…

linux 进程间通信_共享内存

目录 一、什么是共享内存&#xff1f; 二、共享内存的特点 优点 缺点 三、使用共享内存的基本函数 1、创建共享内存shmget() 2、挂接共享内存shmat 3、脱离挂接shmdt 4、共享内存控制shmctl 5.查看和删除共享内存 comm.hpp server.cc Client.cc Makefile 一、什么…

Spring Boot 登录实现:JWT 与 Session 全面对比与实战讲解

Spring Boot 登录实现&#xff1a;JWT 与 Session 全面对比与实战讲解 2025.5.21-23:11今天在学习黑马点评时突然发现用的是与苍穹外卖jwt不一样的登录方式-Session&#xff0c;于是就想记录一下这两种方式有什么不同 在实际开发中&#xff0c;登录认证是后端最基础也是最重要…

Vue中的 VueComponent

VueComponent 组件的本质 Vue 组件是一个可复用的 Vue 实例。每个组件本质上就是通过 Vue.extend() 创建的构造函数&#xff0c;或者在 Vue 3 中是由函数式 API&#xff08;Composition API&#xff09;创建的。 // Vue 2 const MyComponent Vue.extend({template: <div…

使用 FFmpeg 将视频转换为高质量 GIF(保留原始尺寸和帧率)

在制作教程动图、产品展示、前端 UI 演示等场景中,我们经常需要将视频转换为体积合适且清晰的 GIF 动图。本文将详细介绍如何使用 FFmpeg 工具将视频转为高质量 GIF,包括: ✅ 保留原视频尺寸或自定义缩放✅ 保留原始帧率或自定义帧率✅ 使用调色板优化色彩质量✅ 降低体积同…

【自然语言处理与大模型】大模型Agent四大的组件

大模型Agent是基于大型语言模型构建的智能体&#xff0c;它们能够模拟独立思考过程&#xff0c;灵活调用各类工具&#xff0c;逐步达成预设目标。这类智能体的设计旨在通过感知、思考与行动三者的紧密结合来完成复杂任务。下面将从大模型大脑&#xff08;LLM&#xff09;、规划…

《软件工程》第 11 章 - 结构化软件开发

结构化软件开发是一种传统且经典的软件开发方法&#xff0c;它强调将软件系统分解为多个独立的模块&#xff0c;通过数据流和控制流来描述系统的行为。本章将结合 Java 代码示例、可视化图表&#xff0c;深入讲解面向数据流的分析与设计方法以及实时系统设计的相关内容。 11.1 …

初步尝试AI应用开发平台——Dify的本地部署和应用开发

随着大语言模型LLM和相关应用的流行&#xff0c;在本地部署并构建知识库&#xff0c;结合企业的行业经验或个人的知识积累进行定制化开发&#xff0c;是LLM的一个重点发展方向&#xff0c;在此方向上也涌现出了众多软件框架和工具集&#xff0c;Dify就是其中广受关注的一款&…

高阶数据结构——哈希表的实现

目录 1.概念引入 2.哈希的概念&#xff1a; 2.1 什么叫映射&#xff1f; 2.2 直接定址法 2.3 哈希冲突&#xff08;哈希碰撞&#xff09; 2.4 负载因子 2.5 哈希函数 2.5.1 除法散列法&#xff08;除留余数法&#xff09; 2.5.2 乘法散列法&#xff08;了解&#xff09…

7.安卓逆向2-frida hook技术-介绍

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 内容参考于&#xff1a;图灵Python学院 工具下载&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1bb8NhJc9eTuLzQr39lF55Q?pwdzy89 提取码&#xff1…