SLISC 的 matt/matb 文件格式

                     

贡献者: addis

  • 本文存在未完成的内容。
预备知识 SLISC 简介

   SLISC 库提供了两种特殊的文件格式用于储存各种变量和矩阵,每个文件可以存如多个不同的变量(包括矩阵)并指定名称,读取时可以指定要读取的变量名。两种文件分别使用拓展名 .matt.matb。其中 mat 表示 matrix,t 表示 text,b 表示 binary。顾名思义,第一种是文本文件,第二种是二进制文件。二进制文件具有占用硬盘空间少(大约是文本文件的 1/3),读写速度快的优点。文件格式简单,在任何其他语言中都可以轻易地写出读写程序。

   以下给一个 matb 文件的读写例子,也可以把例子中的 matb 换成 matt。

#include "SLISC/matb.h"
using namespace slisc;

int main()
{
    // 随便初始化一些变量, 目前支持 SLISC 库中的绝大部分标量和密矩阵
    Int i = 1; Doub d = 3.1; Comp c(1, 2);
    VecInt v(3); linspace(3, 1, 3); CmatInt a(2,2); linspace(a);

    Matb matb("test.matb", "w"); // 打开 matb 文件, 使用写入模式
    // 相当于 Matb matb; matb.open("test.matb", "w");
    save(i, "i", matb); // 保存变量, 指定变量名, 可以是任意字符串
    save(d, "d", matb); // 注意同个文件中保存的变量名不能重复
    save(c, "c", matb);
    save(v, "c", matb);
    save(a, "a", matb);
    matb.close(); // 关闭文件。
    // 在 destructor 中会自动调用, open() 时也会自动调用

    Int i1; Doub d1; Comp c1; VecInt v1(3); CmatInt a1;
    matb.open("test.matb", "w"); // 重新用读取模式打开文件
    // 读取变量, 可以按照任何顺序, 不需要全部读取
    // 矩阵会被自动 resize()
    load(i1, "i", matb); 
    load(d1, "d", matb);
    load(c1, "c", matb);
    load(v1, "c", matb);
    load(a1, "a", matb);
    matb.close();

    // 此时可以对比读取的变量是否和保存的变量一致
}

1. 文件格式

   我们先介绍二进制格式 matb。matb 文件使用 little endian 储存(通常的 x86 处理器都满足)。所有整数都用 long long(8 字节有符号整型)储存, 每个变量的前 8 个字节是变量名的长度 Nname,然后是 Nname 字节的变量名,紧接着是 8 个字节的矩阵元类型编号(对照表未完成,见 SLISC/preprocessor/type_num.m),8 个字节的矩阵维度 Ndim(标量的维数是 0,向量维度是 1)接着 8*Ndim 字节记录每个维度的长度(标量不需要)。最后,再记录 N * sizeof(元素类型),其中 N 是元素个数,等于各个维度的长度相乘。

   在文件的最后,若一共有 Nvar 个变量,那么就用 Nvar*8 字节记录下每个变量的第一个字节在文件中的字节数(第一个变量总是从第 0 个字节开始)(未完成:目前是倒序的)(另外这些信息只对 matt 有必要),然后再用 8 字节记录下 Nvar,这是为了读取时查找方便。最后为了验证文件的完整性,用 16 字节写入字符串 "Matb_End_of_File"。该字符串用于读取时验证文件的完整性,若不存在则说明文件写入没有完成。事实上 matb 不需要记录该信息,因为逐个变量跳查已经足够快了。matt 使用该信息则可以加快查找变量的速度(因为每个矩阵元在文件中的长度是不等的)。

   对于文本格式 matt,每个整数或浮点数直接转换成字符串写入文本,每两个数之间使用空格隔开,复数则写成两个相邻的数(未完成:现在代码并不是这么做的,而是类似 1+2i)。

2. Matb 类

// all non-data intergers in file are Llong
class Matb {
public:
    Matb();
    Matb(Str_I fname, Char_I rw);
    Char m_rw; // 模式
    ifstream m_in;
    ofstream m_out;
    Llong m_filesize; // 文件大小
    Str m_fname; // 文件名
    vecStr m_name; // 变量名
    vecLlong m_type; // 变量类型
    vector<vecLlong> m_size; // 矩阵尺寸
    vecStr m_data; // 矩阵元二进制数据(仅 "m" 模式使用)
    vecLlong m_ind; // 变量位置

    void open(Str_I fname, Char_I rw); // 打开文件
    Bool isopen(); // 文件是否打开

    // 内部函数
    void read_data(); // 读取到 m_data
    void write_data(Str_I fname); // 写入到 m_data
    Long size() const; // 变量个数
    Long data_size(Long_I i) const; // 第 i 个变量的 m_data 长度
    void get_profile(); // 读取变量信息
    Long data_pos(Long_I var_ind) const; // 第 i 个变量在文件中的位置
    Long search(Str_I name); // 搜索变量编号, 如果不存在返回 -1
    ~Matb();
};

3. 修改模式

   打开 matb 的模式除了 "r", "w" 外还可以是 "m",表示 modify。在该模式下,打开文件后可以对变量进行增加,删除,修改等操作。该功能尚未完善。

4. 其他工具

   可执行文件 SLISC/util/matbinfo 可以显示 matb 文件中的所有变量信息,用法是 matbinfo 文件名.matb

   可执行文件 SLISC/util/matt2matbmatb2matt 可以把 matt 文件和 matb 文件互相转换,例如 matb2matt -d -r 文件名.matb 会生成 文件名.matt。其中 -d 选项在转换后把原文件删除,如果 文件名.matt 已经存在,-r 选项会重新转换并将其替换。

   可执行文件 SLISC/util/matb_q2d 可以把 matb 文件中所有四精度数值转换为双精度(包括 QdoubQcomp)。这样可以方便在不支持四精度的语言中读取(例如 Matlab)。

   Matlab 程序 SLISC/util/mattload.mmatbload.m 分别可以在 Matlab 中读取 mattmatb 文件。


致读者: 小时百科一直以来坚持所有内容免费无广告,这导致我们处于严重的亏损状态。 长此以往很可能会最终导致我们不得不选择大量广告以及内容付费等。 因此,我们请求广大读者热心打赏 ,使网站得以健康发展。 如果看到这条信息的每位读者能慷慨打赏 20 元,我们一周就能脱离亏损, 并在接下来的一年里向所有读者继续免费提供优质内容。 但遗憾的是只有不到 1% 的读者愿意捐款, 他们的付出帮助了 99% 的读者免费获取知识, 我们在此表示感谢。

                     

友情链接: 超理论坛 | ©小时科技 保留一切权利