繁体   English   中英

将人类可读的文件大小解析为字节

[英]Parse human-readable filesizes into bytes

example_strings = ["10.43 KB", "11 GB", "343.1 MB"]

我想将所有这些字符串转换为字节。 到目前为止,我想出了这个:

def parseSize(size):
    if size.endswith(" B"):
        size = int(size.rstrip(" B"))
    elif size.endswith(" KB"):
        size = float(size.rstrip(" KB")) * 1000
    elif size.endswith(" MB"):
        size = float(size.rstrip(" MB")) * 1000000
    elif size.endswith(" GB"):
        size = float(size.rstrip(" GB")) * 10000000000
    elif size.endswith(" TB"):
        size = float(size.rstrip(" TB")) * 10000000000000
    return int(size)

但我不喜欢它,而且我认为它不起作用。 我只能找到做相反事情的模块。

为了回答 OPs 的问题,似乎确实有一个模块,人性化

pip install humanfriendly

然后,

>>> import humanfriendly
>>> user_input = raw_input("Enter a readable file size: ")
Enter a readable file size: 16G
>>> num_bytes = humanfriendly.parse_size(user_input)
>>> print num_bytes
16000000000
>>> print "You entered:", humanfriendly.format_size(num_bytes)
You entered: 16 GB
>>> print "You entered:", humanfriendly.format_size(num_bytes, binary=True)
You entered: 14.9 GiB

这是一个稍微漂亮一点的版本。 可能没有模块,只需定义内联函数。 它非常小且可读。

units = {"B": 1, "KB": 10**3, "MB": 10**6, "GB": 10**9, "TB": 10**12}

# Alternative unit definitions, notably used by Windows:
# units = {"B": 1, "KB": 2**10, "MB": 2**20, "GB": 2**30, "TB": 2**40}

def parse_size(size):
    number, unit = [string.strip() for string in size.split()]
    return int(float(number)*units[unit])


example_strings = ["10.43 KB", "11 GB", "343.1 MB"]

for example_string in example_strings:
    print(parse_size(example_string))

10680
11811160064
359766426

(请注意,不同的地方对 KB、MB 等的定义使用略有不同的约定——使用10**3 = 1000的幂或2**10 = 1024的幂。如果您的上下文是 Windows,您将需要使用后者。如果你的环境是 Mac OS,你会想要使用前者。)

与谷歌中出现的其他所有内容相比,我喜欢Denziloe 的答案,但它

  • 数字和单位之间需要空格
  • 不处理小写单位
  • 假设kb是 1000 而不是 1024,等等。(感谢 mlissner 多年前试图指出这一点。也许我们的假设太老了,但我认为大多数软件也赶不上新假设。)

所以我把它调整成这样:

import re

# based on https://stackoverflow.com/a/42865957/2002471
units = {"B": 1, "KB": 2**10, "MB": 2**20, "GB": 2**30, "TB": 2**40}

def parse_size(size):
    size = size.upper()
    #print("parsing size ", size)
    if not re.match(r' ', size):
        size = re.sub(r'([KMGT]?B)', r' \1', size)
    number, unit = [string.strip() for string in size.split()]
    return int(float(number)*units[unit])

example_strings = ["1024b", "10.43 KB", "11 GB", "343.1 MB", "10.43KB", "11GB", "343.1MB", "10.43 kb", "11 gb", "343.1 mb", "10.43kb", "11gb", "343.1mb"]

for example_string in example_strings:
        print(example_string, parse_size(example_string))

我们可以通过检查输出来验证:

$ python humansize.py 
('1024b', 1024)
('10.43 KB', 10680)
('11 GB', 11811160064)
('343.1 MB', 359766425)
('10.43KB', 10680)
('11GB', 11811160064)
('343.1MB', 359766425)
('10.43 kb', 10680)
('11 gb', 11811160064)
('343.1 mb', 359766425)
('10.43kb', 10680)
('11gb', 11811160064)
('343.1mb', 359766425)

根据小鸡的回答,仅使用正则表达式解析大小并接受整数大小。

UNITS = {None: 1, "B": 1, "KB": 2 ** 10, "MB": 2 ** 20, "GB": 2 ** 30, "TB": 2 ** 40}


def parse_human_size(size):
    """
    >>> examples = [12345, "123214", "1024b", "10.43 KB", "11 GB", "343.1 MB", "10.43KB", "11GB", "343.1MB", "10.43 kb"]
    >>> for s in examples:
        print('[', s, ']', parse_human_size(s))
    """
    if isinstance(size, int):
        return size
    m = re.match(r'^(\d+(?:\.\d+)?)\s*([KMGT]?B)?$', size.upper())
    if m:
        number, unit = m.groups()
        return int(float(number) * UNITS[unit])
    raise ValueError("Invalid human size")

代码搜索包含该字符串的度量单位。 一旦发现。 使用另一个正则表达式,提取数字。 曾经做过这两件事。 将值计算为字节。 如果未指定该值,它会尝试将其视为字节,但如果无法转换,该函数将返回 0。

def calculate(data):

    convertion={"G":1073741824,"M":1048576,"K":1024,"B":1}
    result=re.findall(r'G|M|K|B',data,re.IGNORECASE)
    if len(result)>=1:
        number=re.findall(r'[-+]?\d*\.\d+|\d+', data)
        number=float(number[0])
        return int(number*convertion[result[0].upper()])
    else:
      number=re.findall(r'[-+]?\d*\.\d+|\d+', data)
      if len(number)>=1:
        number=float(number[0])
        return int(number*convertion["B"])
      else:
          return 0

编辑:我错过了另一个答案,它指出了另一个包, humanfriendly ,用于解决这个问题,并且这个包是为这种事情而构建的(与我建议从为完全不同的目的构建的包中偷取实用程序函数相反)。 所以+1那个答案。

我最终来到这里是因为我想避免依赖,但是对于那些不介意的人,你可以在dask.utils.parse_bytes中找到一个非常适合这个的实用程序。

import dask.utils
# supports good range of human-readable units
dask.utils.parse_bytes('150Gi')
161061273600
dask.utils.parse_bytes('150GB')
150000000000
# and potential spelling variants
dask.utils.parse_bytes('150Gb')
150000000000

无论如何,这里是文档这里是源代码 Dask是 python 中的并行计算框架,为花哨的utils而来,为并发而留:)

import re
def parse_size(size):
    units = {"B": 1, "KB": 2**10, "MB": 2**20, "GB": 2**30, "TB": 2**40 ,
             "":  1, "KIB": 10**3, "MIB": 10**6, "GIB": 10**9, "TIB": 10**12}
    m = re.match(r'^([\d\.]+)\s*([a-zA-Z]{0,3})$', str(size).strip())
    number, unit = float(m.group(1)), m.group(2).upper()
    return int(number*units[unit])

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM