Есть ли простой способ в PHP преобразовать из строк, таких как "256M", "180K", "4G" в их целочисленные эквиваленты?
Мне нужно проверить значение, возвращаемое ini_get('memory_limit')
, и увеличить предел памяти, если он ниже определенного порога, однако этот вызов ini_get('memory_limit')
возвращает строковые значения, такие как "128M", а не целые числа.
Я знаю, что могу написать функцию для синтаксического анализа этих строк (учитывая случай и учитывать "В учетную запись" ), поскольку я написал их много раз:
function int_from_bytestring ($byteString) {
preg_match('/^\s*([0-9.]+)\s*([KMGTPE])B?\s*$/i', $byteString, $matches);
$num = (float)$matches[1];
switch (strtoupper($matches[2])) {
case 'E':
$num = $num * 1024;
case 'P':
$num = $num * 1024;
case 'T':
$num = $num * 1024;
case 'G':
$num = $num * 1024;
case 'M':
$num = $num * 1024;
case 'K':
$num = $num * 1024;
}
return intval($num);
}
Однако это становится утомительным, и это похоже на одну из тех случайных вещей, которые уже существуют в PHP, хотя я ее никогда не нашел. Кто-нибудь знает какой-либо встроенный способ анализа этих строк байтов?
Ответы
Ответ 1
Я думаю, тебе не повезло. Руководство PHP для ini_get() действительно устраняет эту проблему в предупреждении о том, как ini_get() возвращает значения ini.
Они предоставляют функцию в одном из примеров, чтобы сделать именно это, поэтому я предполагаю, что это путь:
function return_bytes($val) {
$val = trim($val);
$last = strtolower($val[strlen($val)-1]);
switch($last) {
// The 'G' modifier is available since PHP 5.1.0
case 'g':
$val *= 1024;
case 'm':
$val *= 1024;
case 'k':
$val *= 1024;
}
return $val;
}
У них есть это, чтобы сказать о вышеперечисленной функции: "В приведенном выше примере показан один способ преобразования сокращенной нотации в байты, как это делает PHP-источник".
Ответ 2
Или немного более короткая версия, если хотите
function toInteger ($string)
{
sscanf ($string, '%u%c', $number, $suffix);
if (isset ($suffix))
{
$number = $number * pow (1024, strpos (' KMG', strtoupper($suffix)));
}
return $number;
}
Ответ 3
От веб-сайта PHP для ini_get()
:
function return_bytes($val) {
$val = trim($val);
$last = strtolower($val[strlen($val)-1]);
switch($last) {
// The 'G' modifier is available since PHP 5.1.0
case 'g':
$val *= 1024;
case 'm':
$val *= 1024;
case 'k':
$val *= 1024;
}
return $val;
}
Ответ 4
Я могу только думать о небольшом изменении того, что вы делаете:
function int_from_bytestring($byteString) {
$ret = 0;
if (preg_match('!^\s*(\d+(?:\.\d+))\s*([KMNGTPE])B?\s*$!', $byteString, $matches)) {
$suffix = " KMGTPE";
$index = strpos($suffix, $matches[2]);
if ($index !== false) {
$ret = $matches[1];
while ($index--) {
$matches *= 1024;
}
}
}
return intval($ret);
}
Ответ 5
Поскольку вы получите сообщение об ошибке с более новыми версиями PHP, если в конце значения указан CHAR, вам может потребоваться дополнительное тестирование:
private function toBytes($str){
$val = trim($str);
$last = strtolower($str[strlen($str)-1]);
if (!is_numeric($last)) {
$val = substr($val,0,strlen($val)-1);
switch($last) {
case 'g': $val *= 1024;
case 'm': $val *= 1024;
case 'k': $val *= 1024;
}
}
return $val;
}
Это работает без предупреждений
Ответ 6
даже если приведенные выше решения верны, оператор switch
без break
не очень интуитивен и для улучшения читабельности, чтобы выразить то, что действительно происходит, я бы предпочел сделать это следующим образом:
/**
* @return int maximum memory limit in [byte]
*/
private static function takeMaximumFootprint()
{
$memory = ini_get('memory_limit');
$byte = intval($memory);
$unit = strtolower($memory[strlen($memory) - 1]);
switch ($unit) {
case 'g':
$byte *= 1024 * 1024 * 1024; break;
case 'm':
$byte *= 1024 * 1024; break;
case 'k':
$byte *= 1024; break;
}
return $byte;
}