7

私はphp(1GB +)で大きなテキストファイルを扱っています、私は使用しています

file_get_contents("file.txt", NULL, NULL, 100000000,100); 

ファイルの途中からデータを取得するには、ファイル内のデータを元のデータとは異なるものに変更したい場合は、ファイル全体を書き直す必要があります。

データが元よりも大きい場合、データを上書きせずにファイル (可変長) 内のデータを変更するにはどうすればよいですか? ファイル内のさまざまなデータ ブロックとそのバイト位置のインデックスを保持しています。唯一の代替手段は、データの各部分に x 量のバイトを割り当て、それを変更したい場合はそのブロックを書き直すことです...これの問題は、必要以上に多くのスペースを占めることですnullバイト、そして書き込みに時間がかかります...そして、ファイルのサイズが縮小することは決してないため、それでもデータを「削除」する方法は解決されません...ここで本当に助けが必要です...

ファイル内のデータの各部分に接頭辞付きのブロックを使用した場合 (1 mb など)、データを入力したかった100kbのは .最初の専用ブロック以上を上書きするため、データを削除することはできません...削除することはできません...これが意味をなすことを願っています...代替手段を探しているのではなく、途中でデータを書き込んで変更しようとしていますファイル、へへ…

更新:はい、古いデータを置き換えたいのですが、新しいデータが古いデータよりも拡張されている場合は、残りのデータをファイルにさらにプッシュする必要があります...

これを考慮してください: 0000000HELLODATA00000000 ゼロは空のスペースを表し、何もありません... 今度は、HELLO を SOMETHING に置き換えたいと思います。何かが hello よりも大きいため、hello の開始点に書き込むだけで、hello を超えて拡張され、データの上書きが開始されます.. . したがって、データをファイルにさらにプッシュして、データを上書きせずに何かのためのスペースを確保したいと思います...へへ

4

3 に答える 3

11

データを上書きするには:

$fp = fopen("file.txt", "rw+");
fseek($fp, 100000000); // move to the position
fwrite($fp, $string, 100); // Overwrite the data in this position 
fclose($fp);

データを注入するには

rewriteファイルにアクセスする必要があるため、これは注意が必要です。ファイル全体ではなくpartial modificationfromで最適化できますpoint of injection

$string = "###INJECT THIS DATA ##### \n";
injectData("file.txt", $string, 100000000);

使用する機能

function injectData($file, $data, $position) {
    $fpFile = fopen($file, "rw+");
    $fpTemp = fopen('php://temp', "rw+");

    $len = stream_copy_to_stream($fpFile, $fpTemp); // make a copy

    fseek($fpFile, $position); // move to the position
    fseek($fpTemp, $position); // move to the position

    fwrite($fpFile, $data); // Add the data

    stream_copy_to_stream($fpTemp, $fpFile); // @Jack

    fclose($fpFile); // close file
    fclose($fpTemp); // close tmp
}
于 2013-05-29T12:11:17.470 に答える
3

関数の別のバリアントinjectData():

function injectData($file, $data, $position) 
{
    $temp = fopen('php://temp', "rw+");
    $fd = fopen($file, 'r+b');

    fseek($fd, $position);
    stream_copy_to_stream($fd, $temp); // copy end

    fseek($fd, $position); // seek back
    fwrite($fd, $data); // write data

    rewind($temp);
    stream_copy_to_stream($temp, $fd); // stich end on again

    fclose($temp);
    fclose($fd);
}

ファイルの終わり (以降) を一時ファイルにコピーし$position、データを書き込むために戻ってシークし、すべてをバックアップします。

于 2013-05-29T13:37:04.033 に答える
2

ババの答えの変形、より大きなファイルで作業する場合により効率的かどうかはわかりません:

function injectData($file, $data, $position) {
    $fpFile = fopen($file, "rw+");
    $fpTemp = fopen('php://temp', "rw+");
    stream_copy_to_stream($fpFile, $fpTemp, $position);
    fwrite($fpTemp, $data);
    stream_copy_to_stream($fpFile, $fpTemp, -1, $position);

    rewind($fpFile);
    rewind($fpTemp);
    stream_copy_to_stream($fpTemp, $fpFile);

    fclose($fpFile);
    fclose($fpTemp);
}

injectData('testFile.txt', 'JKL', 3);

stream_copy_to_stream() 呼び出しの 1 つを排除する以前の方法のバリアントなので、少し速くなるはずです。

function injectData3($file, $data, $position) {
    $fpFile = fopen($file, "rw+");
    $fpTemp = fopen('php://temp', "rw+");
    stream_copy_to_stream($fpFile, $fpTemp, -1, $position);
    fseek($fpFile, $position);
    fwrite($fpFile, $data);
    rewind($fpTemp);
    stream_copy_to_stream($fpTemp, $fpFile);

    fclose($fpFile);
    fclose($fpTemp);
}
于 2013-05-29T13:25:02.077 に答える