4 回答

TA貢獻1844條經驗 獲得超8個贊
假設您的數據相當對稱,最性能友好的選項就是簡單地array_chunk()
將數組切割成塊,當json_encode
d 時,這些塊將大約是預期的大小。讓我們看一下數組中的樣本:
string(58)?"{"category":"1795","email":null,"level":1,"name":"BARFOO"}"
這里的“名稱”似乎是唯一可能變化更大的一個。我們將其平均為 12 個字符,每個項目的字符串長度為 64 字節。然后,您可以將其中的 78125 個放入 5MB 中。為了將其保持在標記之下,我們將其設置為 75000。然后,$chunks = array_chunk($data, 75000)
將為您提供 X 個大約或略低于 5MB 標記的塊。
現在,如果您想要更精確,并且尺寸確實很重要......我們可以:
$size = 0; // size counter
$chunkno = 1; // chunk number
$maxbytes = 50000; // 50000-byte chunks
$chunks = []; // for array chunks
foreach($data as $set) {
? ? // if over the limit, move on to next chunk
? ? if ($size > $maxbytes) {?
? ? ? ? $size = 0;
? ? ? ? $chunkno++;
? ? }
? ? $size += strlen(json_encode($set)) + 1; // add a comma's length!
? ? $chunks[$chunkno][] = $set;
}
// unset($data); // in case you have memory concerns
顯然,我們在這里使用 json_encode 執行雙重任務,但塊大小不會受到源數據差異的影響。我針對 50000 字節的塊運行了上面的測試腳本,您需要將其5000000用于您的用例。我生成的虛擬數據最多分為整齊的 50K 塊。+/- 一組的大小,加上最后一個文件中的剩余部分。
在思考這個問題時,我也考慮過這樣做strlen(implode(,但考慮到 PHP 的總體性能很好json_encode,為了獲得精確的 JSON 字符串大小而進行權衡,不應該有太多的損失。
無論如何,一旦塊準備好了,我們需要做的就是把它們寫下來:
foreach($chunks as $n => $chunk) {
? ? $json = json_encode($chunk);
? ? file_put_contents("tmp/chunk_{$n}.json", $json);
}
...或者匹配您的塊命名和目錄架構。
也許有更聰明的方法可以做到這一點。也就是說,據我所知,核心 PHP 中沒有任何內容可以開箱即用地執行此類操作(即使對于普通數組也是如此),并且上述操作應該執行得相當好。請記住有足夠的可用內存。:)
PS 在計算大小時,我們為每個項目添加 +1,代表{},{},{},或對象分隔符。嚴格來說,您還需要在總計中添加 +2,因為它將是[{},{},{}],而我們只將每個數組項的長度作為單獨的 JSON 對象進行計算。對于其他數據結構,您的補償里程可能會有所不同。
優化更新:如果您選擇“精確大小”方法并希望優化內存使用,最好將 JSON 提交集成到分塊循環中。(感謝@NigelRen的建議。)如下(其他初始變量如前):
$chunk = [];
foreach($data as $n => $set) {
? ? if ($size > $maxbytes) {
? ? ? ? file_put_contents("tmp/chunk_{$chunkno}.json", json_encode($chunk));
? ? ? ? $chunk = [];
? ? ? ? $chunkno++;
? ? ? ? $size = 0;
? ? }
? ? $size += strlen(json_encode($set)) + 1;
? ? $chunk[] = $set;
? ? //? unset($data[$n]); // in case of memory issues, see notes
}
如果您對影響感到好奇。通過這種方法,內存使用量達到(已用,最大)1.06 MB、29.34 MB。使用單獨的寫入例程,26.29 MB、31.8 MB。兩個數字都包括unset($data)調用、取消初始數組并釋放內存。CPU 方面,兩個選項之間沒有顯著差異。
人們還可以$data在每次添加到 后清除數組的成員$chunk[],但是在 5MB 塊大小下,這里的內存優勢可以忽略不計。初始數組本身的加載/定義是昂貴的,是最大內存使用量的主要因素。(在任何處理開始之前,我使用的測試數組占用了 29.25 MB。)

TA貢獻1895條經驗 獲得超7個贊
您可以獲取strlen字節并從那里進行計算:
$total_size = strlen(json_encode($array)) / 1024 / 1024;
$chunk_size = floor($total_size / 5);
$chunked_array = array_chunk($array, $chunk_size);
foreach($chunked_array as $key => $chunk) {
$i = $key + 1;
file_put_contents("file{$i}.json", json_encode($chunk));
}
獲取 JSON 編碼數組的總大?。ㄒ宰止潪閱挝唬┎⑥D換為 MB
將總大小除以 5MB 即可得到塊大小
將數組分成塊大小
循環和 JSON 編碼每個塊并寫入文件
或者您可以進行計算:
$total_size = strlen(json_encode($array)); $chunk_size = floor($total_size / (5 * 1024 * 1024));

TA貢獻1801條經驗 獲得超8個贊
讓我們假設每個項目都具有相同的結構:
1500 項 ~= 5MB
25500 items = ~85MB
85MB / 5MB = 17
25500 / 17 = 1500 items
代碼可以是這樣的:
foreach(array_chunk($array, 1500) as $arr){
// save array in some file
}

TA貢獻1829條經驗 獲得超9個贊
請嘗試以下解決方法:
<?php
$array = array (
0 => array (
'category' => '179535',
'email' => NULL,
'level' => 1,
'name' => 'FOO'
),
1 => array (
'category' => '1795',
'email' => NULL,
'level' => 1,
'name' => 'BARFOO'
),
2 => array (
'category' => '16985',
'email' => NULL,
'level' => 1,
'name' => 'FOOBAR'
)
);
$len = sizeof($array);
$fileNameIndex = 1;
for($i=0;$i<$len;$i++)
{
$fileName = 'file'.$fileNameIndex.'.json';
$fileExist = file_exists($fileName);
$fileSize = 0;
$mode ='w';
$current = null;
if($fileExist)
{
$fileSize = fileSize($fileName);
$current = json_decode(file_get_contents($fileName), true);
}
if($fileExist && $fileSize < 5242880)
{
WriteToFile($fileNameIndex, $current, $array[$i], $i);
}
else if(!$fileExist)
{
WriteToFile($fileNameIndex, $current, $array[$i], $i);
}
else
{
$fileNameIndex ++;
WriteToFile($fileNameIndex, $current, $array[$i], $i);
}
}
function WriteToFile($fileNameIndex, $current, $data, $i)
{
$fileName = 'file'.$fileNameIndex.'.json';
$mode ='w';
echo "$i index array is being written in $fileName. <br/>";
$fileNameIndex ++;
$fp = fopen($fileName, $mode);
if($current)
{
array_push($current, $data);
}
else
{
$current = [];
array_push($current, $data);
}
fwrite($fp, json_encode($current));
fclose($fp);
}
?>
- 4 回答
- 0 關注
- 164 瀏覽
添加回答
舉報