タブで区切られたdoubleの配列を含む最大100万のテキストファイルを生成しています(これらは研究用のシミュレーションです)。以下の出力例。100万個のテキストファイルごとに最大5TBになると予想されますが、これは許容できません。だから私は圧縮する必要があります。
ただし、私のデータ分析はすべてmatlabで行われます。そして、すべてのmatlabスクリプトは、これらの数百万のテキストファイルすべてにアクセスする必要があります。HDスペースが不足しているため、C++を使用して100万個全体を解凍してからmatlabスクリプトを実行することはできません。だから私の質問は、C ++で圧縮を記述してmatlabで読み取ることができるように、テキストファイルのサイズを縮小する非常にシンプルで実装が簡単なアルゴリズムやその他の方法はありますか?
サンプルテキストファイル
0.0220874 0.00297818 0.000285954 1.70E-05 1.52E-07
0.0542912 0.00880725 0.000892849 6.94E-05 4.51E-06
0.0848582 0.0159799 0.00185915 0.000136578 7.16E-06
0.100415 0.0220033 0.00288016 0.000250445 1.38E-05
0.101889 0.0250725 0.00353148 0.000297856 2.34E-05
0.0942061 0.0256 0.00393893 0.000387219 3.01E-05
0.0812377 0.0238492 0.00392418 0.000418365 4.09E-05
0.0645259 0.0206528 0.00372185 0.000419891 3.23E-05
0.0487525 0.017065 0.00313825 0.00037539 3.68E-05
重要な場合は、完全なテキストファイルは同時確率質量関数を表すため、合計は1になります。可逆圧縮が必要です。
更新これは、C ++でバイナリを記述してMatlabで読み取るための、非常に基本的な説明を含むIDIOTSガイドです。
小さな配列をバイナリファイルに書き込むためのC++コード。
#include <iostream>
using namespace std;
int main()
{
float writefloat;
const int rows=2;
const int cols=3;
float JPDF[rows][cols];
JPDF[0][0]=.19493;
JPDF[0][1]=.111593;
JPDF[0][2]=.78135;
JPDF[1][0]=.33333;
JPDF[1][1]=.151535;
JPDF[1][2]=.591355;
JPDFは、6つの値を保存するfloat型の配列です。これは2x3アレイです。
FILE * out_file;
out_file = fopen ( "test.bin" , "wb" );
正直なところ、最初の行が何をしているのかよくわかりません。out_fileという名前のFILE型のポインタを作成しているようです。2行目のfopenは、書き込み用の新しいファイル(2番目のパラメーターの「w」)を作成し、それをバイナリファイル(wbの「b」)にすることを示しています。
fwrite(&rows,sizeof(int),1,out_file);
fwrite(&cols,sizeof(int),1,out_file);
ここでは、配列のサイズ(#行、#列)をエンコードします。変数自体ではなく、変数の行と列への参照をfwriteすることに注意してください(&はrefによるものです)。2番目のパラメーターは、書き込むバイト数を示します。行と列はどちらもintなので、sizeof(int)を使用します。「1」はこれを1回行うと言います。おもう。そして、out_fileは、書き込み先のファイルへのポインターです。
for (int i=0; i<3; i++)
{
for (int j=0; j<2; j++)
{
writefloat=JPDF[j][i];
fwrite (&writefloat , sizeof(float), 1, out_file);
}
}
fclose (out_file);
return 0;
}
次に、配列を反復処理し、各値をバイト単位でファイルに書き込みます。インデックス付けは、内側のループの列全体ではなく、各列を繰り返し処理しているという点で、少し後ろ向きです。その理由はすぐにわかります。繰り返しになりますが、writefloatへの参照を記述しています。これは、各反復で現在の配列要素の値を取ります。各配列要素はfloatであるため、ここではsizeof(int)の代わりにsizeof(float)を使用しています。
信じられないほど、ばかげて明確にするために、これが私が今作成したファイルについてどう思うかを示す図です。
[4 bytes: rows][4 bytes: cols][4 bytes: JPDF[0][0]][4 bytes: JPDF[1][0]] ...
[4 bytes: JPDF[1][2]]
..バイトの各チャンクはバイナリ(0と1)で書き込まれます。
MATLABで解釈するには:
FID=fopen('test.bin');
sizes=fread(FID,2,'int')
FIDは、ここではポインタのように機能します。密かに、それはおそらくポインタです。次に、C++フレッドと非常によく似た動作をするフレッドを使用します。FIDは、ファイルへの「ポインタ」です。'int'は、各チャンクに含まれるバイト数を関数に通知します。つまりsizes=fread(FID,2,'int')
、'FIDをバイナリで開き、サイズINTバイトの2つのチャンクを読み取り、2つの要素をベクトル形式で返します。ここで、sizes(1)= rows、sizes(2)=colsです。
s=fread(FID,[sizes(1) sizes(2)],'float')
次の部分は元々私には完全には明確ではありませんでした。行/列情報を含むバイナリの「ヘッダー」をスキップするようにfreadに指示する必要があると思いました。ただし、中断した場所へのポインタを密かに保持します。そこで、配列の次元がわかっているという事実を利用して、残りのバイナリファイルを空にします。2番目のパラメーター[M、N]は[rows、cols]ですが、freadは「列順」で読み取るため、配列データを列順で書き込んだことに注意してください。
1つ*は、C ++プログラムのアーキテクチャがmatlabと一致している場合(たとえば、両方が64ビット、または両方が32ビット)にのみ、matlabコード'int'および'float'を使用できると思います。しかし、これについてはよくわかりません。
出力は次のとおりです。
sizes =
2
3
s =
0.194930002093315 0.111593000590801 0.781350016593933
0.333330005407333 0.151535004377365 0.59135502576828