| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105 |
- // Package bytefmt contains helper methods and constants for converting to and from a human-readable byte format.
- //
- // bytefmt.ByteSize(100.5*bytefmt.MEGABYTE) // "100.5M"
- // bytefmt.ByteSize(uint64(1024)) // "1K"
- //
- package bytefmt
- import (
- "errors"
- "fmt"
- "regexp"
- "strconv"
- "strings"
- )
- const (
- BYTE = 1.0
- KILOBYTE = 1024 * BYTE
- MEGABYTE = 1024 * KILOBYTE
- GIGABYTE = 1024 * MEGABYTE
- TERABYTE = 1024 * GIGABYTE
- )
- var bytesPattern *regexp.Regexp = regexp.MustCompile(`(?i)^(-?\d+(?:\.\d+)?)([KMGT]i?B?|B)$`)
- var invalidByteQuantityError = errors.New("Byte quantity must be a positive integer with a unit of measurement like M, MB, MiB, G, GiB, or GB")
- // ByteSize returns a human-readable byte string of the form 10M, 12.5K, and so forth. The following units are available:
- // T: Terabyte
- // G: Gigabyte
- // M: Megabyte
- // K: Kilobyte
- // B: Byte
- // The unit that results in the smallest number greater than or equal to 1 is always chosen.
- func ByteSize(bytes uint64) string {
- unit := ""
- value := float32(bytes)
- switch {
- case bytes >= TERABYTE:
- unit = "T"
- value = value / TERABYTE
- case bytes >= GIGABYTE:
- unit = "G"
- value = value / GIGABYTE
- case bytes >= MEGABYTE:
- unit = "M"
- value = value / MEGABYTE
- case bytes >= KILOBYTE:
- unit = "K"
- value = value / KILOBYTE
- case bytes >= BYTE:
- unit = "B"
- case bytes == 0:
- return "0"
- }
- stringValue := fmt.Sprintf("%.1f", value)
- stringValue = strings.TrimSuffix(stringValue, ".0")
- return fmt.Sprintf("%s%s", stringValue, unit)
- }
- // ToMegabytes parses a string formatted by ByteSize as megabytes.
- func ToMegabytes(s string) (uint64, error) {
- bytes, err := ToBytes(s)
- if err != nil {
- return 0, err
- }
- return bytes / MEGABYTE, nil
- }
- // ToBytes parses a string formatted by ByteSize as bytes. Note binary-prefixed and SI prefixed units both mean a base-2 units
- // KB = K = KiB = 1024
- // MB = M = MiB = 1024 * K
- // GB = G = GiB = 1024 * M
- // TB = T = TiB = 1024 * G
- func ToBytes(s string) (uint64, error) {
- parts := bytesPattern.FindStringSubmatch(strings.TrimSpace(s))
- if len(parts) < 3 {
- return 0, invalidByteQuantityError
- }
- value, err := strconv.ParseFloat(parts[1], 64)
- if err != nil || value <= 0 {
- return 0, invalidByteQuantityError
- }
- var bytes uint64
- unit := strings.ToUpper(parts[2])
- switch unit[:1] {
- case "T":
- bytes = uint64(value * TERABYTE)
- case "G":
- bytes = uint64(value * GIGABYTE)
- case "M":
- bytes = uint64(value * MEGABYTE)
- case "K":
- bytes = uint64(value * KILOBYTE)
- case "B":
- bytes = uint64(value * BYTE)
- }
- return bytes, nil
- }
|