| Crates.io | moduforge-file |
| lib.rs | moduforge-file |
| version | 0.7.0 |
| created_at | 2025-08-19 09:36:35.111148+00 |
| updated_at | 2025-11-14 06:20:17.141862+00 |
| description | moduforge 文件 |
| homepage | https://github.com/Cassielxd/moduforge-rs |
| repository | https://github.com/Cassielxd/moduforge-rs |
| max_upload_size | |
| id | 1801638 |
| size | 190,228 |
一个高性能、高可靠性的文件格式处理库,专为现代应用程序的数据持久化需求设计。提供了双格式支持,兼顾极致性能和跨平台兼容性。
graph TB
A[ModuForge File] --> B[单文件格式 .mff]
A --> C[ZIP容器格式 .ysf]
B --> D[record.rs<br/>基础记录读写]
B --> E[document.rs<br/>分段文档]
C --> F[zipdoc/writer.rs<br/>ZIP写入器]
C --> G[zipdoc/reader.rs<br/>ZIP读取器]
C --> H[zipdoc/formats/<br/>多格式支持]
I[error.rs<br/>统一错误处理] --> A
J[history.rs<br/>历史记录] --> A
| 特征 | 单文件格式 (.mff) | ZIP容器格式 (.ysf) |
|---|---|---|
| 性能 | ⭐⭐⭐⭐⭐ 极致 | ⭐⭐⭐⭐ 优秀 |
| 文件大小 | ⭐⭐⭐⭐⭐ 最小 | ⭐⭐⭐ 良好 |
| 随机访问 | ⭐⭐⭐ 支持 | ⭐⭐⭐⭐⭐ 优秀 |
| 跨平台性 | ⭐⭐⭐⭐ 良好 | ⭐⭐⭐⭐⭐ 完美 |
| 调试友好 | ⭐⭐ 基础 | ⭐⭐⭐⭐⭐ 优秀 |
| 标准兼容 | ⭐⭐⭐ 自定义 | ⭐⭐⭐⭐⭐ ZIP标准 |
[dependencies]
moduforge-file = "0.1.0"
use moduforge_file::{Writer, Reader, Result};
fn basic_example() -> Result<()> {
// 创建写入器,预分配64MB提升性能
let mut writer = Writer::create("data.mff", 64 * 1024 * 1024)?;
// 追加数据记录,返回偏移量
let offset1 = writer.append(b"Hello, ModuForge!")?;
let offset2 = writer.append(b"High performance storage")?;
// 确保数据落盘
writer.flush()?;
// 读取数据
let reader = Reader::open("data.mff")?;
let data1 = reader.get_at(offset1)?;
let data2 = reader.get_at(offset2)?;
println!("数据1: {}", String::from_utf8_lossy(data1));
println!("数据2: {}", String::from_utf8_lossy(data2));
Ok(())
}
use moduforge_file::{DocumentWriter, DocumentReader, SegmentType, Result};
use serde_json::json;
fn document_example() -> Result<()> {
// 创建分段文档
let mut writer = DocumentWriter::begin("document.mff")?;
// 添加元数据段
let metadata = json!({
"title": "示例文档",
"version": "1.0.0",
"created": "2024-01-01T00:00:00Z",
"author": "ModuForge Team"
});
let meta_bytes = serde_json::to_vec(&metadata)?;
writer.add_segment(SegmentType::Meta, &meta_bytes)?;
// 添加模式定义段
let schema = br#"<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="root" type="xs:string"/>
</xs:schema>"#;
writer.add_segment(SegmentType::Schema, schema)?;
// 添加快照数据段
let snapshot_data = bincode::serialize(&vec!["data1", "data2", "data3"])?;
writer.add_segment(SegmentType::Snapshot, &snapshot_data)?;
// 完成写入,自动生成目录和校验
writer.finalize()?;
// 读取文档
let reader = DocumentReader::open("document.mff")?;
if let Some(meta) = reader.read_segment(SegmentType::Meta)? {
let metadata: serde_json::Value = serde_json::from_slice(meta)?;
println!("文档标题: {}", metadata["title"]);
}
if let Some(snapshot) = reader.read_segment(SegmentType::Snapshot)? {
let data: Vec<String> = bincode::deserialize(snapshot)?;
println!("快照数据: {:?}", data);
}
Ok(())
}
use moduforge_file::{
ZipDocumentWriter, ZipDocumentReader,
SnapshotFormat, export_zip_with_format
};
use std::fs::File;
use std::collections::HashMap;
fn zip_example() -> std::io::Result<()> {
// 方式一:直接使用 ZipDocumentWriter
let file = File::create("document.ysf")?;
let mut writer = ZipDocumentWriter::new(file)?;
// 添加JSON元数据
let metadata = serde_json::json!({
"title": "ZIP容器示例",
"format": "YSF",
"version": "1.0"
});
writer.add_json("meta.json", &metadata)?;
// 添加压缩的二进制数据
let binary_data = vec![0u8; 1024]; // 示例数据
writer.add_deflated("data.bin", &binary_data)?;
// 添加插件状态
writer.add_plugin_state("auth_plugin", b"user_session_data")?;
writer.add_plugin_state("cache_plugin", b"cached_results")?;
// 完成写入
let _file = writer.finalize()?;
// 方式二:使用高级封装函数
let plugin_states = HashMap::from([
("plugin1".to_string(), b"state1".to_vec()),
("plugin2".to_string(), b"state2".to_vec()),
]);
// 使用MessagePack格式导出
// export_zip_with_format(
// "advanced.ysf",
// &metadata,
// b"<schema>...</schema>", // XML模式
// &shard_meta, // 分片元数据
// |i| Ok(get_shard_data(i)), // 分片数据获取函数
// None, // 父子关系映射
// Some(plugin_states), // 插件状态
// 3, // ZSTD压缩级别
// SnapshotFormat::MsgPack, // 使用MessagePack
// )?;
// 读取ZIP文档
let file = File::open("document.ysf")?;
let mut reader = ZipDocumentReader::new(file)?;
// 读取元数据
let meta_data = reader.read_all("meta.json")?;
let meta: serde_json::Value = serde_json::from_slice(&meta_data)?;
println!("文档标题: {}", meta["title"]);
// 读取所有插件状态
let all_states = reader.read_all_plugin_states()?;
for (plugin_name, state_data) in all_states {
println!("插件 {} 状态大小: {} bytes", plugin_name, state_data.len());
}
Ok(())
}
追加式写入
let mut writer = Writer::create("log.mff", 1024 * 1024)?;
let offset = writer.append(b"log entry")?;
writer.flush()?; // 确保数据持久化
内存映射读取
let reader = Reader::open("log.mff")?;
let data = reader.get_at(offset)?; // 零拷贝读取
批量迭代
let reader = Reader::open("log.mff")?;
for record in reader.iter() {
process_record(record);
}
多格式支持
// JSON格式 - 人类可读,调试友好
writer.add_json("config.json", &json_data)?;
// 二进制格式 - 紧凑高效
writer.add_deflated("data.bin", &binary_data)?;
// 原始存储 - 无压缩开销
writer.add_stored("image.png", &image_data)?;
插件状态管理
// 添加插件状态
writer.add_plugin_state("auth", &auth_state)?;
writer.add_plugin_state("cache", &cache_state)?;
// 批量添加
let states = HashMap::from([
("plugin1".to_string(), state1),
("plugin2".to_string(), state2),
]);
writer.add_plugin_states(states)?;
高级序列化
use moduforge_file::SnapshotFormat;
// 支持多种序列化格式
match format {
SnapshotFormat::Json => { /* JSON序列化 */ }
SnapshotFormat::Cbor => { /* CBOR二进制 */ }
SnapshotFormat::MsgPack => { /* MessagePack */ }
}
测试环境: Intel i7-10700K, NVMe SSD, 32GB RAM
单文件格式 (.mff):
├─ 顺序写入: ~2.1 GB/s
├─ 随机写入: ~1.8 GB/s
├─ 小记录写入: ~850K ops/s
└─ 预分配写入: ~2.4 GB/s
ZIP容器格式 (.ysf):
├─ 压缩写入: ~450 MB/s
├─ 存储模式: ~1.2 GB/s
├─ JSON写入: ~380 MB/s
└─ 二进制写入: ~680 MB/s
单文件格式 (.mff):
├─ 顺序读取: ~3.2 GB/s (零拷贝)
├─ 随机读取: ~2.8 GB/s
├─ 迭代访问: ~920K ops/s
└─ 并发读取: 线性扩展
ZIP容器格式 (.ysf):
├─ 解压读取: ~680 MB/s
├─ 直接访问: ~1.8 GB/s
├─ 随机访问: ~1.5 GB/s
└─ 插件状态读取: ~520 MB/s
单文件格式:
├─ 写入缓冲: 8MB (可配置)
├─ mmap开销: 0字节 (虚拟内存)
└─ 元数据: ~128字节/文件
ZIP容器格式:
├─ 解析开销: ~2KB/条目
├─ 压缩缓冲: 64KB-1MB
└─ manifest: ~50字节/条目
use moduforge_file::{FileError, ErrorSeverity};
match error {
FileError::Io(io_err) => {
// IO错误:文件系统问题
if error.is_retryable() {
retry_operation();
}
}
FileError::BadHeader => {
// 格式错误:文件损坏
recover_from_backup();
}
FileError::CrcMismatch(offset) => {
// 校验失败:数据损坏
report_corruption(offset);
}
FileError::RecordTooLarge(size) => {
// 大小超限:分割数据
split_large_record(size);
}
}
fn robust_operation() -> Result<()> {
let mut retries = 3;
loop {
match risky_operation() {
Ok(result) => return Ok(result),
Err(e) if e.is_retryable() && retries > 0 => {
retries -= 1;
std::thread::sleep(Duration::from_millis(100));
continue;
}
Err(e) if e.is_data_corruption() => {
return handle_corruption(e);
}
Err(e) => return Err(e),
}
}
}
// 为频繁写入预分配空间
let writer = Writer::create("data.mff", 100 * 1024 * 1024)?;
// 批量写入减少系统调用
let offsets: Vec<u64> = records.iter()
.map(|record| writer.append(record))
.collect::<Result<Vec<_>>>()?;
// 大批量写入后再flush
for record in large_dataset {
writer.append(&record)?;
}
writer.flush()?; // 一次性刷新
// 周期性验证数据完整性
fn verify_file(path: &Path) -> Result<bool> {
let reader = Reader::open(path)?;
for record in reader.iter() {
// 迭代过程中会自动校验CRC
process_record(record);
}
Ok(true)
}
// 写入前创建备份点
std::fs::copy("data.mff", "data.mff.backup")?;
let mut writer = Writer::create("data.mff", 0)?;
// ... 写入操作
writer.flush()?;
std::fs::remove_file("data.mff.backup")?;
use std::sync::Arc;
// 多读者共享
let reader = Arc::new(Reader::open("data.mff")?);
let handles: Vec<_> = (0..num_threads)
.map(|_| {
let reader = reader.clone();
std::thread::spawn(move || {
// 并发读取操作
reader.get_at(offset)
})
})
.collect();
// 等待所有线程完成
for handle in handles {
handle.join().unwrap()?;
}
┌─────────────────┬─────────────────┬─────────────────┬─────────────┐
│ 文件头(16B) │ 记录1 │ 记录2 │ 尾指针 │
├─────────────────┼─────────────────┼─────────────────┼─────────────┤
│ MAGIC(8) + 预留 │ 长度+CRC+数据 │ 长度+CRC+数据 │ 可选的快速索引 │
└─────────────────┴─────────────────┴─────────────────┴─────────────┘
记录格式:
┌──────────┬──────────┬─────────────────┐
│ 长度(4B) │ CRC32(4B)│ 负载数据(变长) │
├──────────┼──────────┼─────────────────┤
│ Little │ CRC32 │ 用户数据 │
│ Endian │ 校验码 │ │
└──────────┴──────────┴─────────────────┘
document.ysf (ZIP Archive)
├── meta.json # 元数据 (JSON)
├── schema.xml # 数据模式 (XML/Binary)
├── snapshot_0.msgpack # 分片数据 (MessagePack)
├── snapshot_1.msgpack # 分片数据 (MessagePack)
├── parent_map.msgpack # 关系映射 (可选)
├── plugins/ # 插件状态目录
│ ├── auth_plugin # 认证插件状态
│ ├── cache_plugin # 缓存插件状态
│ └── custom_plugin # 自定义插件状态
└── manifest.json # ZIP清单 (自动生成)
// 从文件头开始顺序扫描,找到有效数据的边界
pub fn scan_logical_end(mmap: &Mmap) -> Result<u64> {
let mut pos = HEADER_LEN;
while pos + REC_HDR <= mmap.len() {
let length = read_u32_le(&mmap[pos..pos + 4]) as usize;
if length == 0 { break; } // 零长度表示结束
let payload_start = pos + REC_HDR;
let payload_end = payload_start + length;
if payload_end > mmap.len() { break; } // 超出文件边界
// 校验CRC32
let stored_crc = read_u32_le(&mmap[pos + 4..pos + 8]);
let computed_crc = crc32(&mmap[payload_start..payload_end]);
if stored_crc != computed_crc { break; } // 校验失败
pos = payload_end;
}
Ok(pos as u64)
}
fn ensure_capacity(&mut self, needed: u64) -> Result<()> {
if self.prealloc_chunk == 0 { return Ok(()); } // 禁用预分配
let required = self.logical_end + needed;
if required <= self.prealloc_until { return Ok(()); } // 已有足够空间
// 按块扩展,避免频繁系统调用
let mut new_size = self.prealloc_until;
while new_size < required {
new_size += self.prealloc_chunk;
}
self.buf.flush()?; // 刷新缓冲区
self.file.set_len(new_size)?; // 扩展文件
self.prealloc_until = new_size;
Ok(())
}
欢迎贡献代码!请遵循以下流程:
git checkout -b feature/amazing-featuregit commit -m 'Add amazing feature'git push origin feature/amazing-feature# 克隆仓库
git clone https://github.com/moduforge/moduforge-rs.git
cd moduforge-rs/crates/file
# 运行测试
cargo test
# 运行基准测试
cargo bench
# 生成文档
cargo doc --open
cargo fmt 格式化代码cargo clippy 进行代码检查本项目采用双重许可:
您可以选择任一许可证使用本软件。