2

ネイティブおよびマネージド C++ で、4 GB 以上の大きなアーカイブ ファイル(以下を参照)用のエディターを作成しています。

ファイルにアクセスするために、私は普通の人のようにファイル マッピング(下記参照) を使用しています。これはデータの読み取りには非常に優れていますが、実際にアーカイブを編集する際に問題が発生します。ファイル マッピングでは、アクセス中にファイルのサイズを変更することはできないため、ユーザーがファイルに新しいデータを挿入したい場合 (マップされたときのファイルの元のサイズを超えてしまう)、どのように処理すればよいかわかりません。

毎回全体を再マップする必要がありますか? それは遅いはずです。ただし、排他的なファイル アクセスを使用してエディターをリアルタイムに維持したいと考えています。これにより、プログラミングが大幅に簡素化され、変更中に他のアプリケーションによってファイルが台無しにされることがなくなります。私はエディタの作業に永遠を費やしたくありません。これは、私が取り組んでいる実際のプロジェクトの単純な開発ツールです。

同様のケースをどのように処理したか、また、他のアーカイブ ソフトウェア、特に他のゲームでこれを解決する方法を教えてください。

明確にするために:

  • これはテキスト ファイルではなく、特定のバイナリアーカイブ ファイル形式で記述しています。これは、ディレクトリ内に他の多くのファイルを含む大きなファイルを意味します。カスタム アーカイブ ファイルは、さまざまな理由から、ゲームの使用において非常に一般的です。私のフォーマットでは、Valve Software の GCF フォーマットと同様の (ただし、やや単純な) 構造を目指しています。GCF フォーマットをそのまま使用することもできますが、残念ながらこのフォーマット用のエディターは存在しません。HLLibのように、それらを読み取るため。

  • ゲーム リソースの保存を目的としているため、ファイルへのアクセスは高速である必要があります。したがって、データベースではありません。データベースファイルは、GFX、SFX などのファイルとともに、その中に含まれます。

  • ここで説明する「ファイル マッピング」は、Windows プラットフォームでの特定の手法であり、大きなファイルの一部に「ビュー」を作成することで、大きなファイルに直接アクセスできます。こちらを参照してください: http://msdn.microsoft.com/en-us /library/aa366556(VS.85).aspx - この手法により、待機時間とメモリ使用量を最小限に抑えることができ、大きなファイルに簡単にアクセスできます。したがって、これは4GB のファイル全体をメモリに読み込むという意味ではなく、まったく逆です。

4

6 に答える 6

2

「エディタソフトウェア」とはどういう意味ですか?これがテキストファイルの場合、独自のエディターを作成する前に、既存のプロダクション品質のエディターを試しましたか?バイナリデータを格納するファイルの場合、RDBMSを使用し、SQLステートメントを使用してその内容を操作することを検討しましたか?

どうしてもこれを最初から書く必要があるのなら、mmappingが進むべき道かどうかはわかりません。巨大なファイルをマッピングすると、マシンのVMシステムに大きなプレッシャーがかかります。ファイル全体に多くの編集操作がない限り、その効率は単純な読み取り/書き込みスキームに遅れをとる可能性があります。さらに悪いことに、あなたが言うように、ファイルを拡張したいときに問題が発生します。

代わりに、ユーザーが変更できるファイルのデータへのバッファーウィンドウを維持します。ユーザーがファイルを保存することを決定したら、ファイルと編集されたバッファを順番にトラバースして、新しいファイルイメージを作成します。ディスク容量がある場合は(特にバッファのサイズが変更されている場合)、新しいファイルを作成する方が簡単です。そうでない場合は、新しいコンテンツで上書きする前に、既存のデータを先読みする方法を慎重に検討する必要があります。

または、編集操作のジャーナルを保持することもできます。ユーザーがファイルを保存することを決定したら、ジャーナルでトポロジカルソートを実行し、既存のファイルで再生して新しいファイルを作成します。

排他的なファイルアクセスの場合は、オペレーティングシステムのファイルロックを使用するか、アプリケーションレベルのロックを実装します(エディターのみがこれらのファイルにアクセスする場合)。排他的アクセスのmmapに応じて、実装の選択が制限されます。

于 2008-10-12T17:38:17.147 に答える
2

ファイルのマッピングは、実際にデータにアクセスするために作成されますが、ファイルの構造を表す別の抽象化が必要だと思います。これを行うにはさまざまな方法がありますが、ファイルを「エクステント」のシーケンスとして表すことを検討してください。

ファイルから始めることは、マッピング全体に相当する単一のエクステントです。その後、ユーザーがファイルの編集を開始した場合、編集ポイントで1つのエクステントを2つに分割し、ユーザーが挿入したデータを含む新しいエクステントを挿入します。変更および削除は、これらのエクステントを作成または変更することにより、ファイルのビューも変更します。

オープンソースエディタの1つのソースコードを調べることができるかもしれません-選択できるものはたくさんありますが、十分に単純なものを見つけるのは難しいでしょう。

于 2008-10-12T17:46:35.240 に答える
1

ビューハンドルとFileMappingハンドルを閉じ、ファイルサイズを設定してから、マッピング/ビューハンドルを再度開きます。

// Open memory mapped file    
HANDLE FileHandle = ::CreateFileW(file_name, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
size_t Size = ::GetFileSize(FileHandle, 0);
HANDLE MappingHandle = ::CreateFileMapping(FileHandle, NULL, PAGE_READWRITE, 0, Size, NULL);
void* ViewHandle = ::MapViewOfFile(MappingHandle, FILE_MAP_ALL_ACCESS, 0, 0, Size);

...

// increase size of file
UnmapViewOfFile(ViewHandle);
CloseHandle(MappingHandle);

Size += 1024;


LARGE_INTEGER offset;
offset.QuadPart = Size;

LARGE_INTEGER newpos;
SetFilePointerEx(FileHandle, offset, &newpos, FILE_BEGIN);
SetEndOfFile(FileHandle);

MappingHandle = ::CreateFileMapping(FileHandle, NULL, PAGE_READWRITE, 0, Size, NULL);
ViewHandle = ::MapViewOfFile(MappingHandle, FILE_MAP_ALL_ACCESS, 0, 0, Size);

上記のコードにはエラーチェックがなく、64ビットサイズを処理しませんが、修正するのは難しくありません。

于 2008-10-12T23:03:37.427 に答える
1

この問題に対する簡単な答えはありません。私は長い間答えを探してきましたが、無駄でした。ファイルのサイズを変更してから、再マップする必要があります。

于 2008-10-12T18:12:01.400 に答える
1

マッピングには、リモート システム上のファイルに関する基本的な問題があります。

古き良きDOS時代には、Norton Editor(ne.com ..これはファイル名であり、Webサイトではありません)と呼ばれる優れたエディターがありました。任意のサイズのファイルをロードできます (640kb の RAM と 20 GB のハードディスクについて話しています)。

以前はファイルの一部のみをロードしていましたが、オンデマンド ロードでファイルの長い検索を巧みに管理していました

私見、そのようなアプローチを使用する必要があります。

file-read-write layer の下に適切に隠せば、驚くほど透明になります。

于 2009-01-31T13:03:32.027 に答える
0

ビルド時に断片から大きなファイルをビルドします。通常のファイル システム (必要に応じてサブディレクトリなどを使用) で、エディタに通常のフラット ファイルを処理させます。次に、これらすべての断片をまとめてアーカイブファイル形式にするコンパイル ステップがあります。

于 2009-04-20T15:44:02.850 に答える