Contents of this directory is archived and no longer updated.

В PowerShell есть замечательная возможность нативно оперировать с этими префиксами. Достаточно написать размер в килобайтах или мегабайтах, PowerShell автоматически переведёт его в байты:

[vPodans] 5kb
5120
[vPodans] 10mb
10485760
[vPodans] 40gb
42949672960
[vPodans]

Видите, все значения сами переводятся в байты. Особо не перестарайтесь, потому что TB не является константой и автоматически не преобразовывается. Но когда мы собираем информацию о системе, например, объём физической памяти или жёстких дисков средствами WMI, то данные обычно указываются в байтах и приходится вручную их как-то переводить в килобайты, мегабайты или гигабайты. Штатного функционала для решения данной задачи нету, поэтому приходится использовать примерно такой ход:

(2048 / 1kb).tostring("F00")

и в результате мы получим число 2. Мы 2048 байт разделили на килобайты, чтобы получить значение в килобайтах (если делим на 1MB, то значение получим в мегабайтах соответственно) с округлением до целого числа. Для округления до определённого знака после запятой, то в скобках нужно указать точность, например:

[vPodans] (20000 / 1kb).tostring("F00")
20
[vPodans] (20000 / 1kb).tostring("F01")
19,5
[vPodans] (20000 / 1kb).tostring("F02")
19,53
[vPodans] (20000 / 1kb).tostring("F03")
19,531
[vPodans]

используя эти данные можно написать простенькую функцию, которая будет делать обратное преобразование. Причём она это будет делать автоматически, т.е. сама выбирать в чём отображать значение, в байтах, килобайтах, мегабайтах или гигабайтах. Критерии выбора префикса очень простые - числа от 1 до 1000. Если число выше, то увеличиваем префикс до тех пор, пока не получим число от 1 до 1000. Например, 10485760 делим на 1kb и получаем 10240 килобайт. Такое представление не очень понятное. Поэтому мы ещё раз разделим на 1kb и получим цифру 10, но префикс уже будет - мегабайты. Вот такую функцию предложил Rob Campbell на ньюсгруппах (я её немного подрихтовал, чтобы выглядела более элегантно):

function to_kmg ($bytes, [int]$precision = 0) {
foreach ($i in ("Bytes","KB","MB","GB","TB")) {
    if (($bytes -lt 1024) -or ($i -eq "TB")){
        $bytes = ($bytes).tostring("F0" + "$precision")
        return $bytes + " $i"
        } else {
            $bytes /= 1KB
        }
    }
}

функция просто по очереди перебирает префиксы и проверяет, чтобы число было в пределах от 0 до 1024 (для двоичной системы мне кажется, что лучше использовать именно 1024, а не 1000). Если нет (а оно значит больше, чем 1024), то добавляем следующий префикс и уменьшаем число снова на 1024. Вот так просто это делается. Попробуем проверить функцию на примерах, которые были показаны в самом начале поста:

[vPodans] function to_kmg ($bytes, [int]$precision = 0) {
>> foreach ($i in ("Bytes","KB","MB","GB","TB")) {
>>     if (($bytes -lt 1000) -or ($i -eq "TB")){
>>         $bytes = ($bytes).tostring("F0" + "$precision")
>>         return $bytes + " $i"
>>         } else {
>>             $bytes /= 1KB
>>         }
>>     }
>> }
>>
[vPodans] to_kmg 5120
5 KB
[vPodans] to_kmg 10485760
10 MB
[vPodans] to_kmg 42949672960
40 GB
[vPodans]

Второй аргумент ($precision) позволяет указывать точность значения в знаках после запятой. Вот почти и всё. Однако, есть одно "но". WMI некоторые размеры отдаёт не в байтах (как для дисков), а в килобайтах (как для физической памяти). Поэтому для работы этой функции аргумент $bytes должен быть либо точного размера в байтах, либо с явным указанием префикса (например, 100kb).

Кстати говоря, тут будет полезным почитать по двоичным и десятичным префиксом. Порядок применения префиксов описан в документе IEC-60027-2:

По этим ссылкам достаточно понятно объясняется что такое десятичный префикс и двоичный, а так же и проблемы их использования в компьютерной технике.


Share this article:

Comments:

http://xaegr.livejournal.com/

А я уже писал эту функцию :Р http://xaegr.wordpress.com/2007/12/07/human-readable/ Кстати в 2.0 можно так: [PS <10> C:\Root] 1tb 1099511627776 [PS <11> C:\Root] 1pb 1125899906842624

Vadims Podāns

Не знал, честно. :( пойду поищу стенку какую, что ли..

Comments are closed.