亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

PHP從一個數組創建多個給定大小的json文件

PHP從一個數組創建多個給定大小的json文件

PHP
qq_笑_17 2023-10-01 10:09:47
我想從一個數組創建多個 json 文件(file1.json、file2.json 等),并且每個文件的最大文件大小必須為 5 mb。我有這樣的數組:    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'    ),    ....        25500 => array (        'category' => '10055',        'email' => NULL,        'level' => 1,        'name' => 'FOOBARBAR'    )    )如果我用 json_encode($arr) 將其寫入文件中。生成的文件大約為 85mb。那么如何拆分該數組以使每個文件最多 5 MB?
查看完整描述

4 回答

?
婷婷同學_

TA貢獻1844條經驗 獲得超8個贊

假設您的數據相當對稱,最性能友好的選項就是簡單地array_chunk()將數組切割成塊,當json_encoded 時,這些塊將大約是預期的大小。讓我們看一下數組中的樣本:

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。)


查看完整回答
反對 回復 2023-10-01
?
人到中年有點甜

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));



查看完整回答
反對 回復 2023-10-01
?
蝴蝶刀刀

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


}


查看完整回答
反對 回復 2023-10-01
?
PIPIONE

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);

    }

?>


查看完整回答
反對 回復 2023-10-01
  • 4 回答
  • 0 關注
  • 164 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號