在進行程式設計的時候,有時會需要進行檔案大小或是資料大小的輸入與輸出,甚至會需要對其做一些運算。做這件事有什麼困難的嗎?我們應該都知道,8個位元是1個位元組(Byte),1000個位元組是1KB,而1000KB是1MB。在設計程式的時候,如果要將一個以位元組為單位的值,選擇適當的單位來輸出(例如1200位元組要輸出成1.20MB、5555555位元組要輸出成5.56MB)的話,就必須要多撰寫幾行程式來完成。如果是資料輸入的時候,假設使用者輸入的是「3.6MB」,程式也許需要多撰寫幾行程式,將其轉為「3600000」來儲存,表示為「3600000個位元組」;輸入「25KB」,就要轉成「25000」。這些雖然都是簡單的事情,且所需要的程式碼量也不大,但就是由於簡單又常用,每次都要在不同專案寫一樣的程式去處理就會覺得很煩躁,所以乾脆將其發展為一個獨立的套件,就能不斷地重複使用了。



Byte Unit

「Byte Unit」是筆者開發的套件,實現了位元組(B)、KB、KiB、MB、MiB、GB、GiB、TB、TiB、PB、PiB、EB、EiB、ZB、ZiB、YB、YiB的大小單位換算。

KB、MB、GB、TB、PB、EB、ZB、YB等都是基於1000的單位,而KiB、MiB、GiB、TiB、PiB、EiB、ZiB、YiB等則是基於1024的單位。

1KB  = 1000
1KiB = 1024
1MB  = 1000000
1MiB = 1048576
1GB  = 1000000000
1GiB = 1073741824
1TP  = 1000000000000
1TiB = 1099511627776
1PB  = 1000000000000000
1PiB = 1125899906842624
1EB  = 1000000000000000000
1EiB = 1152921504606846976
1ZB  = 1000000000000000000000
1ZiB = 1180591620717411303424
1YB  = 1000000000000000000000000
1YiB = 1208925819614629174706176

預設儲存位元組的數值型別是採用u64,不過也可以啟用u128特色來改為使用u128數值型別,最大支援的單位才會從EiB變成YiB。

Crates.io

Cargo.toml

byte-unit = "*"

使用方法

Unit

Unit列舉可以表示位元或是位元組的單位。

use byte_unit::Unit;

assert_eq!("KB", Unit::KB.as_str());
assert_eq!("MiB", Unit::MiB.as_str());

assert_eq!(Unit::KB, Unit::parse_str("K", true, true).unwrap());
assert_eq!(Unit::Kbit, Unit::parse_str("K", true, false).unwrap());

assert_eq!(Unit::KB, Unit::parse_str("KB", true, true).unwrap());
assert_eq!(Unit::KB, Unit::parse_str("Kb", true, true).unwrap());
assert_eq!(Unit::Kbit, Unit::parse_str("Kbit", true, true).unwrap());

assert_eq!(Unit::KB, Unit::parse_str("KB", false, true).unwrap());
assert_eq!(Unit::Kbit, Unit::parse_str("Kb", false, true).unwrap());
Byte

Byte結構體可以表示位元組的大小。

from_*關聯函數可以被用來從不同的資料型別建立Byte實體。as_*方法能以基本資料型別來取得大小。

use byte_unit::{Byte, Unit};

assert_eq!(15000, Byte::from_u64(15000).as_u64());
assert_eq!(15000, Byte::from_u64_with_unit(15, Unit::KB).unwrap().as_u64());

我們也可以解析一個字串剌產生初一個Byte實體。

use byte_unit::Byte;

assert_eq!(50840000, Byte::parse_str("50.84 MB", true).unwrap().as_u64());

一個Byte實體可以被精確地格式化成字串。更多用法請參考API文件。

use byte_unit::Byte;

let byte = Byte::from_u64(15500);

assert_eq!("15500", byte.to_string());

assert_eq!("15.5 KB", format!("{byte:#}"));
assert_eq!("15500 B", format!("{byte:#.0}"));
計算

addsubtractmultiplydivide方法可以使用。

use byte_unit::Byte;

let a = Byte::from_u64(15500);
let b = Byte::from_u64(500);

assert_eq!(16000, a.add(b).unwrap().as_u64());
assert_eq!(15000, a.subtract(b).unwrap().as_u64());

assert_eq!(31000, a.multiply(2).unwrap().as_u64());
assert_eq!(3100, a.divide(5).unwrap().as_u64());
找出適當的單位

如果我們想要替某個Byte實體找出適當的單位,get_exact_unitget_recoverable_unit方法很有用。

use byte_unit::{Byte, Unit};

let byte = Byte::from_u64(50840000);

assert_eq!((50840, Unit::KB), byte.get_exact_unit(false));
assert_eq!((50.84f64.try_into().unwrap(), Unit::MB), byte.get_recoverable_unit(false, 2));
assert_eq!((50840.into(), Unit::KB), byte.get_recoverable_unit(false, 0));
AdjustedByte

AdjustedByte結構體可以被用來粗略地表示位元組的大小和單位。

我們可以使用get_adjusted_unit方法來改變某個Byte實體的單位。

一個AdjustedByte實體可以被格式化成字串。更多用法請參考API文件。

use byte_unit::{Byte, Unit};

let byte = Byte::parse_str("123KiB", true).unwrap();

let adjusted_byte = byte.get_adjusted_unit(Unit::KB);

assert_eq!("125.952 KB", adjusted_byte.to_string());
assert_eq!("125.95 KB", format!("{adjusted_byte:.2}"));

get_appropriate_unit方法可以被用來自動地替Byte實體找到一個合適的單位來產生AdjustedByte實體。

use byte_unit::{Byte, Unit, UnitType};

let byte = Byte::from_u64(1500000);

let adjusted_byte = byte.get_appropriate_unit(UnitType::Binary);

assert_eq!("1.43 MiB", format!("{adjusted_byte:.2}"));
Bit

Bit結構體可以表示位元組的大小。

必須啟用bit特色。

Bit結構體的用法和Byte結構體非常相似。也有AdjustedBit結構體能用。有差異的地方在於Bitparse_str方法不能夠設定為忽略大小寫,它總是不會忽略大小寫。

use byte_unit::{Bit, Unit};

let bit = Bit::parse_str("123Kib").unwrap();

let adjusted_bit = bit.get_adjusted_unit(Unit::Kbit);

assert_eq!("125.952 Kb", adjusted_bit.to_string());
assert_eq!("125.95 Kb", format!("{adjusted_bit:.2}"));