本文已参与「新人创作礼」活动,一起开启掘金创作之路。 在计算机中计算文件大小, 内存或者存储大小时, 通常会以字节或者比特为单位.
而在以字节或者字符显示内存或者存储大小时, 通常有2种方式进行计算.
一种是严格遵从计算机科学的逻辑, 以2的幂的方式进行计算; 另外一种则是为方便人类计算的方式, 以10的幂的方式进行计算.
而以2进制计算大小时, 通常单位是: "B", "KiB", "MiB", "GiB", "TiB", "PiB", 其中后者是前者的1024倍, 如 1KiB = 1024B.
而以10进制计算大小时, 通常单位是: "B", "KB", "MB", "GB", "TB", "PB", 其中后者是前者的1000倍, 如 1KB = 1000B.
因而, 在以不同的方式计算 4567B是多少KB/Kib 时, 结果是不相同的.
而大神 JakeWharton 的 byteunits 项目, 就是来进行这种转换的.
byteunits支持10进制和2进制两种不同的计算方式.
byteunits项目定义了接口:
sealed interface ByteUnit {
fun toBytes(count: Long): Long
}
用于以指定的单位计算特定数目的字节时, 是多个字符. 为避免误解, 下面将会举例说明.
接口ByteUnit有3个实现类: BinaryByteUnit, DecimalByteUnit, BitUnit. 它们都是枚举类, 诸如BinaryByteUnit.KIBIBYTES, DecimalByteUnit.MEGABYTES, BitUnit.BITS. 其中DecimalByteUnit和BitUnit一样采用10进制.
举例说明:
long perception = BinaryByteUnit.TEBIBYTES.toBytes(2)
表示 2TiB 以2进制表示有 perception 个字节.
long usable = DecimalByteUnit.TERABYTES.toBytes(2);
表示 2TB 以10进制表示有 usable 个字节. 而
long lost = BinaryByteUnit.BYTES.toGibibytes(perception - usable)
则表示 以10进制表示的2TB相比于2进制表示的2TiB实际上损失了lost字符.
以上即为两者之间的转化方式.
同时, ByteUnit的实现类也提供了格式化的函数以将字节数转化为人类可读的形式, 如下:
/**
* Return `bytes` as human-readable size string (e.g., "1.2 GiB". This will use a
* [DecimalFormat] instance with `pattern` for formatting the number.
*/
fun format(bytes: Long, pattern: String): String {
return format(bytes, DecimalFormat(pattern))
}
/**
* Return `bytes` as human-readable size string (e.g., "1.2 GiB". This will use a default
* [DecimalFormat] instance for formatting the number.
*/
@JvmOverloads fun format(
bytes: Long,
format: NumberFormat = DecimalFormat(DEFAULT_FORMAT_PATTERN),
): String
/**
* Return `bits` as human-readable size string (e.g., "1.2 Gb". This will use a
* [DecimalFormat] instance with [pattern] for formatting the number.
*/
fun format(bits: Long, pattern: String): String {
return format(bits, DecimalFormat(pattern))
}
/**
* Return `bits` as human-readable size string (e.g., "1.2 Gb". This will use a default
* [DecimalFormat] instance for formatting the number.
*/
@JvmOverloads fun format(
bits: Long,
format: NumberFormat = DecimalFormat(DEFAULT_FORMAT_PATTERN),
): String
如果有需求, 可以尝试一下 byteunits, 确实有帮助.