mirror of
https://github.com/Light-City/CPlusPlusThings.git
synced 2026-10-28 19:04:45 +08:00
- const README: rewrite the space-saving claim per issue #5 follow-ups (constant-expression const vs #define immediates; which const qualify as constant expressions) - const README: fix the class-section diagnosis per issue #338 (overload resolution picks the const overload; the restriction only surfaces once that overload is removed) - sizeof README: virtual-inheritance result is compiler-dependent (GCC merges vbptr+vfptr -> 16, MSVC keeps them separate -> 32) #246 - static README: new section on internal linkage / access restriction with anonymous-namespace comparison #142 - 10-day practice: full problem list table + fixed day links #136 - new design_pattern/singleton/singleton_default.hpp: reusable thread-safe CRTP singleton template, compile+concurrency tested #303
134 lines
3.4 KiB
Markdown
134 lines
3.4 KiB
Markdown
> 来自 [C++那些事网站](https://light-city.github.io/stories_things/cpp-projects/cpp17-sqlite-folder-size/) 的文章,由站点同步脚本导出。
|
||
|
||
# C++17 与 SQLite 统计目录大小
|
||
|
||
## 项目实战:使用 C++17 和 SQLite 实现文件夹大小计算与存储
|
||
|
||
[TOC]
|
||
|
||
本节将会围绕一个项目背景展开:假设业务中需要定时检查某些文件夹大小,并做一下持久化操作,C++如何去完成这一个项目呢?
|
||
|
||
本节带你通过一个小项目,使用 C++17 和 SQLite 实现一个文件夹大小计算与存储的系统,帮助你更好地管理你的文件系统。
|
||
|
||
### 项目目标
|
||
|
||
我们将实现以下功能:
|
||
1. **递归计算指定目录及其子目录的大小**。
|
||
2. **将计算结果保存到 SQLite 数据库**,方便后续查询和分析。
|
||
3. **可扩展性强**:你可以轻松修改项目,添加多线程支持、优化性能,或将结果存储到其他数据库中。
|
||
|
||
**注:懒人版,完整代码已更新星球。**
|
||
|
||
### 项目实现步骤
|
||
|
||
#### 1. 环境
|
||
|
||
首先,你需要确保开发环境中已经安装了以下工具:
|
||
- **支持C++17 编译器**:如 g++,通过以下命令可以检查版本:
|
||
|
||
```bash
|
||
g++ --version
|
||
```
|
||
确保 g++ 支持 C++17 标准。
|
||
|
||
- **SQLite3**:数据库操作我们会使用 SQLite,你可以通过包管理器来安装它:
|
||
```bash
|
||
sudo apt-get install sqlite3 libsqlite3-dev
|
||
```
|
||
安装完后,SQLite 数据库的开发库 `libsqlite3-dev` 可以确保我们在 C++ 中能正常使用 SQLite。
|
||
|
||
#### 2. 创建项目结构
|
||
|
||
我们将把代码分为多个模块,保持清晰的架构:
|
||
- `folder_size.h` / `folder_size.cpp`:负责递归计算目录及其子目录大小。
|
||
- `database.h` / `database.cpp`:封装 SQLite 数据库操作逻辑。
|
||
- `main.cpp`:主程序入口,负责整体流程的控制。
|
||
|
||
项目的目录结构如下:
|
||
```
|
||
project/
|
||
│── folder_size.h
|
||
│── folder_size.cpp
|
||
│── database.h
|
||
│── database.cpp
|
||
└── main.cpp
|
||
```
|
||
|
||
#### 3. 代码实现
|
||
|
||
接下来,我们将一步步实现每个模块。
|
||
|
||
##### 3.1 目录计算模块
|
||
|
||
C++17 提供了`std::filesystem` 库来递归遍历目录并计算大小。因此其核心实现如下:
|
||
|
||
```cpp
|
||
uintmax_t total_size = 0;
|
||
for (const auto& entry : fs::recursive_directory_iterator(dir_path)) {
|
||
if (fs::is_regular_file(entry.path())) {
|
||
total_size += fs::file_size(entry.path());
|
||
}
|
||
}
|
||
```
|
||
|
||
如果要计算根目录 再计算一次即可。
|
||
|
||
##### 3.2 SQLite数据库操作
|
||
|
||
引入:
|
||
|
||
```
|
||
#include <sqlite3.h>
|
||
```
|
||
|
||
使用:
|
||
|
||
```cpp
|
||
sqlite3_close(db_); // 关闭
|
||
|
||
// 插入
|
||
for (const auto& [folder, size] : folder_sizes) {
|
||
const std::string insert_sql =
|
||
"INSERT OR REPLACE INTO FolderSizes (Folder, Size) "
|
||
"VALUES ('" + folder + "', " + std::to_string(size) + ");";
|
||
if (!ExecuteSQL(insert_sql)) {
|
||
return false;
|
||
}
|
||
}
|
||
|
||
// 执行
|
||
sqlite3_exec
|
||
```
|
||
|
||
#### 4. 编译与运行
|
||
|
||
编译项目非常简单:
|
||
|
||
```bash
|
||
mkdir build
|
||
cmake ../
|
||
make -j8
|
||
```
|
||
|
||
然后,运行程序,计算目录大小并存储到数据库:
|
||
|
||
```bash
|
||
./folder_size_calculator
|
||
```
|
||
|
||
程序将会递归计算指定目录的大小,并将结果保存到 `folder_sizes.db` 数据库中。
|
||
|
||
#### 5. 查询数据库
|
||
|
||
最后,你可以通过
|
||
|
||
SQLite 命令行工具查询数据库中的内容:
|
||
|
||
```bash
|
||
sqlite3 folder_sizes.db
|
||
sqlite> SELECT * FROM FolderSizes;
|
||
```
|
||
|
||
这将显示所有已保存的目录及其对应的大小。
|
||
|
||
> 本节完 |