私は非常に大きなバイナリファイルを扱います(ファイルごとに数GBから数TB)。これらのファイルはレガシー形式で存在し、アップグレードするにはファイルのFRONTにヘッダーを書き込む必要があります。新しいファイルを作成してデータを書き換えることはできますが、時間がかかる場合があります。このアップグレードを達成するためのより速い方法があるかどうか疑問に思います。プラットフォームはLinuxに限定されており、これを実現するために低レベルの関数(ASM、C、C ++)/ファイルシステムのトリックを使用したいと思っています。プライマリライブラリはJavaであり、JNIは完全に受け入れられます。
5 に答える
これをネイティブに行う一般的な方法はありません。
たぶん、いくつかのファイルシステムはこれを行うためのいくつかの関数を提供します(これについてのヒントを与えることはできません)が、あなたのコードはファイルシステムに依存します。
解決策は、ファイルシステムをシミュレートすることです。データを複数のファイルのセットに保存し、単一のファイルであるかのようにデータを開いたり、読み取ったり、書き込んだりするためのいくつかの機能を提供できます。
クレイジーに聞こえますが、ファイルからデータを読み取る機能を変更できる場合は、ファイルデータを逆の順序で保存できます。その場合、ファイルの最後にデータを(逆の順序で)追加できます。これは単なる一般的な考え方なので、特にお勧めすることはできません。現在のファイルを元に戻すためのコードは次のようになります。
std::string records;
ofstream out;
std::copy( records.rbegin(), records.rend(), std::ostream_iterator<string>(out));
それはあなたが「ファイルシステムのトリック」によって何を意味するかによります。ファイルシステムのディスク上のフォーマットを気にせず、追加するヘッダーのサイズがファイルシステムのブロックサイズの倍数である場合は、ファイルシステムを直接操作するプログラムを作成できます。ディスク上の構造(ファイルシステムがマウントされていない状態)。
しかし、この企業は見た目と同じくらい毛深いです-処理するこれらの巨大なファイルが何百もある場合にのみ価値があるでしょう。
私はそれを行うために標準のLinuxツールを使用するだけです。
別のアプリケーションを作成してそれを行うのは、最適ではないようです。
cat headerFile oldFile > tmpFile && mv tmpFile oldFile
これは古い質問ですが、将来誰かに役立つことを願っています。ファイルシステムのシミュレーションと同様に、名前付きパイプを使用するだけで済みます。
mkfifo /path/to/file_to_be_read
{ echo "HEADER"; cat /path/to/source_file; } > /path/to/file_to_be_read
次に、に対してレガシープログラムを実行する/path/to/file_to_be_readと、入力は次のようになります。
HEADER
contents of /path/to/source_file
...
これは、プログラムがファイルを順番に読み取り、バッファを実行mmap()または通過しない限り機能します。rewind()