• 締切済み

巨大ファイルの結合

Win98を対象としたファイル結合ソフトを作りました。 newでメモリ確保してaとbを結合しますが、結合後に2Gになるものなら空き領域が2Gぐらい必要なのでそのような場合には使えないソフトとなってしまいました。 空き領域がほとんど無くて、1.9Gのaに0.1Gのbを結合してaを上書きする感じで結合させたいのですが、アセンブラ以外の方法を教えてください。

みんなの回答

  • tea_sheep
  • ベストアンサー率53% (8/15)
回答No.5

> ANo.4 メモリマップトファイルの場合は後からサイズ拡張できないので あらかじめファイルサイズを2GBにしておかなければならないのと、 Win9X系ではファイル全体が共有メモリ領域(1GB)にマッピング できなければいけないという制約があったりして、この場合には 適用できないかと。NT/2k系だと部分的にマッピングしたりとか してできるとは思いますが。 やっぱりNo3の方の追加モードがベストな手段だと思います。

elngr
質問者

お礼

あらかじめファイルサイズを2GBにしておかなければならないということではメモリマップトファイルは今回は使えませんね。

  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.4

★『メモリ・マップドファイル』という技術を利用するのは?どう。 ・これはファイルをメモリのように扱える方法でメモリコピーの関数で追加など出来ます。  今回のように巨大なファイルやディスク容量に限りがある場合には有効な手段だと私は思います。 ・『巨大ファイルの合併』方法としては、  (1)1.9GバイトのファイルAを『メモリ・マップドファイル』に割り付ける。→α  (2)0.1GバイトのファイルBを『メモリ・マップドファイル』に割り付ける。→β  (3)αデータのポインタ位置を最後に移動する。→α += 1.9Gのサイズ分;  (4)αデータのポインタ位置にβデータをメモリ・コピー関数で結合する。→MemoryCopy(α,β,0.1Gのサイズ);  (5)α、βの『マップドファイル』のメモリ割り付けを解除する。→普通のファイルに戻る。  (6)巨大ファイル 1.9Gバイト(α) に 0.1Gバイト(β)のデータが結合する。 ・これならばメモリ確保しなくても良いし、1.9Gバイトのファイルに上書きした感じで結合されます。 最後に: ・『メモリ・マップドファイル』は『CreateFileMapping』API関数で行えますが、MFCなら専用のクラスが  あります。MFC は使ったことがないため詳しくありませんが、ファイルをメモリに変換する方法が今回の  『メモリ・マップドファイル』の事です。 ・http://www.fsinet.or.jp/~madcap/memmap.html→『メモリマップドファイル』 ・http://homepage2.nifty.com/DSS/WinSys/Win/FileMapping.htm→『メモリマップドファイル』 ・http://www.h6.dion.ne.jp/~game296o/DXCLS_MemoryMappedFile.html→『メモリマップドファイルクラス』 ・すべて C/C++ で実装できます。アセンブラ以外です。ただ1点、『メモリ・マップドファイル』で 1.9 G  の巨大ファイルが扱えたかどうか良く覚えていません。上限は 1G バイトだったような気が…。 ・もしも、1G 以上が扱えなかった場合は、回答者 No.3 さんの方法が有効になります。  追加モードで 1.9G バイトのファイルを開き、0.1G バイトのファイルを読み込み専用でオープンして  単純に fread、fwrite して合併すれば良いでしょう。 ・以上です。参考に!

参考URL:
http://www11.ocn.ne.jp/~ikalu/win32api/0014.html
elngr
質問者

お礼

(1)~(6)の手順を見るとできそうですね。 試してみます。

回答No.3

普通は、アペンドモードで a をオープンしたりしますが。 Cなら、 fopen("filename", "a"); // テキストファイル fopen("filename", "ab"); // バイナリファイル C++なら、 ofstream("filename", ios::app); ※テキストファイルならOK,バイナリファイルでやったことはないので不明 これで、a をオープンして、ひたすら、write すればOKです。

elngr
質問者

補足

ありがとうございます。 僕がやりたいことができている結合ソフトがありました。 そのソフトはたぶんアペンドモードでオープンしていたのかもしれませんがアペンドモードのことを忘れていて、作者はたぶんアセンブラを知らないのに何でそんなことが可能なのか不思議でした。

  • chie65536
  • ベストアンサー率41% (2512/6032)
回答No.2

追記 「MS-DOSプロンプト」を起動して、黒いDOS窓で COPY /B a+b c DEL a REN c a の3行を打つと、No.1の回答で説明したプログラムと同じ事をします。 「実はファイル結合ソフトは要らなかった」と言うオチ。 因みに COPY /B a+b+c+d+e f DEL a REN f a で5つのファイルを結合できたりもする。

elngr
質問者

補足

「実はコンベンショナルメモリが足りなかった」と言うオチ。 WinVistaなど知りませんが、黒いDOS窓で2Gを扱うのは無理ではないでしょうか? しかし結合後のファイルサイズが500MBぐらいのものなら僕が作ったソフトより黒いDOS窓でCOPYした方がなぜか高速なのです。

  • chie65536
  • ベストアンサー率41% (2512/6032)
回答No.1

1.256バイトのバッファを確保する 2.cを新規ファイルでライトオープン 3.aをリードオープン 4.aからバッファに256バイト読んでみる 5.読み込めたバイト数がゼロなら8へ 6.読み込めたバイト数だけバッファをcにライトする 7.4に戻る 8.aをクローズする 9.bをリードオープン 10.bからバッファに256バイト読んでみる 11.読み込めたバイト数がゼロなら14へ 12.読み込めたバイト数だけバッファをcにライトする 13.10に戻る 14.bをクローズする 15.cをクローズする 16.aをファイル削除する 17.cをaにリネームする 18.1で確保したバッファを開放する これで、aとbがどれだけ大きくても大丈夫。使うメモリは256バイトだけ。

elngr
質問者

補足

ありがとうございます。 その方法だとendoffile()かtrunc()何かでaのサイズを減らしてゆかなくてはなりません。減らす方法も僕には思いつきません。 HDDの空きは2.1Gで、既に1.9Gのaと0.1Gのbが既存だとして、aにbを結合させるソフトです。

関連するQ&A