(D5)TMemoryStreamの取り扱いで質問です。
複数のファイル(F1, F2, F3, ...., Fn)から、サイズの異なるデータを相次いでメモリストリームに読み込み、これをファイル(Fo)として出力する。
今度は、別のアプリで、Foを読み込み、元々のサイズごと分割して、最初のファイル(F1, F2, F3, ...., Fn)に復元する、という処理を考えています。
seekとかCopyFromメソッドを使えば良さそうだ、ということは理解できたのですが、読み込み元のファイルサイズをどうやって保持すればいいかというのが解決できません。
全てが同じサイズであれば十兵衛さんのSeparateStreamでいいのですが...
何かいい知恵がありましたら、ご教授願います。
書き込み
1)FoにF1ファイルのサイズをIntegerで書き込む
2)FoにF1ファイルの内容を書き込む(CopyFromでいいのかな?)
3)FoにF2ファイルのサイズをIntegerで書き込む
4)FoにF2ファイルの内容を書き込む
・・・
読み込み
1)Integerを読み込みサイズを得る
2)1)で得たサイズ分をFoから読み込み、ファイルに保存する(F1)。
3)Integerを読み込みサイズを得る
4)3)で得たサイズ分をFoから読み込み、ファイルに保存する(F2)。
・・・
とか?
ぽむぽむさん、早速の回答、ありがとうございます。
それですと、1)、3)で「サイズが記録されている部分のサイズ」が分からないと2)、4)の処理ができないのではないでしょうか。
すみません、上記は、読み込み時の場合です。
>それですと、1)、3)で「サイズが記録されている部分のサイズ」が分からないと2)、4)の処理ができないのではないでしょうか。
書き込み時にそれぞれのサイズDATAを4Byte(Integerのサイズ)でStreamに書き込んでいるんだから、
読み込み時にはそのサイズDATA(4Byte分)を読み込めばいいの。
ぽむぽむさん、だから...さんの仰っているのは
ファイルの中身を書き出す前に、そのサイズを保存しておけばOKということです。
procedure PackStream(fi: TStream; fo: TStream);
var
iSize: INT64;
begin
iSize := fi.Size;
fo.WriteBuffer(iSize, SizeOf(iSize)); //←ここでサイズを保存しておく
fo.CopyFrom(fi, 0); //←CopyFrom(fi, iSize)でも一緒
end;
procedure RestoreStream(fi: TStream; fo: TStream);
var
iSize: INT64;
begin
fi.ReadBuffer(iSize, SizeOf(iSize)); //←ここでサイズが分かる
fo.CopyFrom(fi, iSize); //←サイズ分Streamから読み込む
end;
こういうのを作っておいて、結合するときはPackStreamをファイル数だけ読み、
展開するときはRestoreStreamをその数だけ呼べばファイルサイズが分かるということです。
ファイル数が固定ならこれで十分かもしれませんが、不定なら
出力する前にファイル数も入れておくと良いかもしれませんね。
intFileCount = ?←どこかでファイル数が分かる
fo.WriteBuffer(intFileCount, SizeOf(FileCount));
こうしてから、PackStreamをループして呼び出す。
展開するときは
fi := TFileStream.Create(マージしたファイルのパス, fmOpenRead)
fi.ReadBuffer(intFileCount, SizeOf(FileCount)); //←内包しているファイルの数が分かる
for i:=0 to intFileCount-1 do
begin
strPath := パスの生成
fo := TFileStream.Create(strPath, fmCreate);
PackStream(fi, fo);
fo.Free;
end;
fi.Free;
いかがでしょうか。
(動作未確認です)
お返事が遅くなりまして、申し訳ありません。皆さん、どうもありがとうございました。
茶柱さんのおっしゃるとおりのソースで実現できました。
本当に助かりました!!
ツイート | ![]() |