如何在Nim中读写包含seq的自定义二进制数据类型?
在Nim中保存/加载带seq的复杂元组数据结构
针对你定义的带seq[TODO]的TestData元组,有几种直接的方法实现保存和加载:
用marshal模块做二进制序列化
这是最省心的方式,marshal支持直接序列化Nim里绝大多数复杂数据类型,包括嵌套元组和序列:
- 先导入需要的模块:
import marshal, os
- 保存数据:
把TestData转成字节序列后写入文件:
let serializedBytes = toBytes(data) writeFile("testdata.dat", serializedBytes)
- 加载数据:
读取文件字节,再反序列化为TestData:
var loadedData: TestData let fileContent = readFile("testdata.dat") fromBytes(loadedData, fileContent)
注意:这种二进制格式和Nim版本绑定,跨不同版本的Nim加载可能出问题,适合同版本程序内部的数据持久化。
用json模块做文本序列化
如果需要可读的持久化格式,或者要跨版本/跨语言兼容,用JSON更合适:
- 导入模块:
import json, os
- 保存数据:
把数据转成JSON节点,再转成字符串写入文件:
let jsonNode = %data writeFile("testdata.json", $jsonNode)
- 加载数据:
读取JSON字符串,解析后转回TestData类型:
var loadedData: TestData let jsonStr = readFile("testdata.json") loadedData = parseJson(jsonStr).to(TestData)
这种方式生成的文件是纯文本,可读性强,但序列化速度比二进制慢一点。
手动用流自定义二进制格式
如果需要完全控制数据格式(比如最小化文件大小),可以用流和二进制IO手动处理每个字段:
- 导入模块:
import streams, binaryio, os
- 保存数据:
let outputStream = newFileStream("testdata.dat", fmWrite) if outputStream != nil: defer: outputStream.close() # 依次写入TestData的每个字段 write(outputStream, data.timeAdded) write(outputStream, data.who) # 先写seq的长度,方便读取时确定元素个数 write(outputStream, data.todo.len.int32) # 逐个写入seq里的TODO元素 for item in data.todo: write(outputStream, item.atTime) write(outputStream, item.item) write(outputStream, data.isDone)
- 加载数据:
var loadedData: TestData let inputStream = newFileStream("testdata.dat", fmRead) if inputStream != nil: defer: inputStream.close() # 按保存的顺序依次读取字段 read(inputStream, loadedData.timeAdded) read(inputStream, loadedData.who) # 先读seq长度,再初始化seq var todoCount: int32 read(inputStream, todoCount) loadedData.todo = newSeq[TODO](todoCount.int) # 逐个读取TODO元素 for i in 0..<todoCount.int: read(inputStream, loadedData.todo[i].atTime) read(inputStream, loadedData.todo[i].item) read(inputStream, loadedData.isDone)
这种方式代码量最大,但完全可控,适合和其他非Nim程序交互的场景。
内容的提问来源于stack exchange,提问作者IvanS
相关产品推荐
相关产品推荐

