現在行列を (メモリ内に) 格納している構造のタイプは関連しています。
たとえば、次のような構造を使用して二次元行列を格納できます。
struct {
size_t w;
size_t h;
double **values;
size_t n;
char **tags;
}
そして、次のようにディスクに書き込みます。
fwrite(&(m->w), sizeof(size_t), 1, fp);
fwrite(&(m->h), sizeof(size_t), 1, fp);
for (y = 0; y < h; y++)
fwrite(m->values[y], sizeof(double), m->w, fp);
fwrite(&(m->n), sizeof(size_t), 1, fp);
for (y = 0; y < m->n; y++)
{
size_t len = strlen(m->tags[y]);
fwrite(&len, sizeof(size_t), 1, fp);
fwrite(m->tags[y], sizeof(char), len, fp);
}
fwrites を freads に置き換えて再読み込みします。
if (1 != fread(&(m->w), sizeof(size_t), 1, fp))
// ERROR
if (1 != fread(&(m->h), sizeof(size_t), 1, fp))
// ERROR
if (NULL == (m->values = malloc(sizeof(double *) * m->h)))
// ERROR: OUT OF MEMORY
for (y = 0; y < h; y++)
{
if (NULL == (m->values[y] = malloc(sizeof(double) * m->w)))
// OOM
if (m->w != fread(m->values[y], sizeof(double), m->w, fp))
// File truncated error
}
if (1 != fread(&(m->n), sizeof(size_t), 1, fp))
// Truncated
for (y = 0; y < m->n; y++)
{
size_t len;
fread(&len, sizeof(size_t), 1, fp);
if (NULL == (m->tags[y] = malloc(len + 1)))
// OOM
if (len != fread(m->tags[y], sizeof(char), len, fp))
// Truncated
m->tags[y][len] = 0x0; // C strings must be zero-terminated
}
...しかし、これは二次元行列のみをカバーし、各行列を独自のファイルに保存する必要があります。
もちろん、システムをさらに複雑にして、単一の「データベース」にヘッダー、多数のマトリックスなどを保存し、各マトリックスを次々に保存することもできます。
おそらく、長期的には、CLaudixが提案したFITS標準が行列を文字列にシリアライズできるかどうかを確認する方がよいでしょう。そうであれば、それらの文字列を実際のデータベース (PostgreSQL、MySQL、または SQLite3 でさえも) に格納できるため、独立したサーバーを用意する必要はありません)。これにより、タグが変更されるたびに全体を書き直す必要がなくなり、メモリ オブジェクトから SQL 化されたフィールド値に、またはその逆に変換する 2 つの FITS ラップ関数を作成するという代償を払って、コードをより保守しやすくすることができます。
FITS 形式で変数タグを行列やベクトルに関連付けることができない場合、FITS を直接使用すると問題が発生する可能性があります。
文字列オブジェクトへの書き込みに FITS を適合させることができない場合でも、上記のコードを使用して、行列オブジェクトから文字列へのラッパーを書き込むことができる場合があります (たとえば、結果のバッファーを base64 エンコードすることにより)。マトリックスを文字列オブジェクトとして取得したら、そこからは単なる SQL です。
INSERT INTO MatrixTable (matrixId, matrixEncoding) VALUES (...);
INSERT INTO MatrixTags (matrixId, tagName, tagValue) VALUES (2418, 'Taken', '2012-08-20 at noon');