Подтвердить что ты не робот

Есть ли простой способ в 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, хотя я ее никогда не нашел. Кто-нибудь знает какой-либо встроенный способ анализа этих строк байтов?

4b9b3361

Ответ 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;
}