在Dart中格式化文件大小。

4

如何在Dart中格式化文件大小?

输入:1000000

期望输出:1 MB

为方便使用,输入可以是intdouble,结果应该是一个只有一位小数的String

2个回答

8

我为此编写了一个扩展方法:

extension FileFormatter on num {
  String readableFileSize({bool base1024 = true}) {
    final base = base1024 ? 1024 : 1000;
    if (this <= 0) return "0";
    final units = ["B", "kB", "MB", "GB", "TB"];
    int digitGroups = (log(this) / log(base)).round();
    return NumberFormat("#,##0.#").format(this / pow(base, digitGroups)) +
        " " +
        units[digitGroups];
  }
}

对于NumberFormat类,您需要使用intl包进行操作。

您可以使用布尔值base64来显示位或字节。

用法:

int myInt = 12345678;
double myDouble = 2546;
print('myInt: ${myInt.readableFileSize(base1024: false)}');
print('myDouble: ${myDouble.readableFileSize()}');

输出:

myInt: 12.3 MB
myDouble: 2.5 kB

受这个SO回答的启发。


这个答案虽然可行,但不够精确。我有一个大小为65MB的文件,你的函数返回了“0.1GB”,在我的情况下这是没有用的。所以我从这个库https://pub.dev/packages/filesize中复制了这个函数https://github.com/erdbeerschnitzel/filesize.dart/blob/4f7c54dc06647b8368078f6febb83149494698c1/lib/filesize.dart。这不是我见过的最好的实现,但它满足了我的使用需求,并且比你的函数更精确。 - Alex Rintt
与所引用的SO答案相比,这个解决方案遗漏了两个关键点。1)dart:math的log函数是自然对数,而不是以10为底的对数。因为在math库中没有log10函数,所以你可以这样实现它:double log10(final num x) => log(x) / ln10;。2)四舍五入不够精确,使用.floor()将会得到期望的结果。 - Noah Anderson

2
由于上述的方法都不符合我的要求,我将this function转换成了一个更简单易读、更灵活的版本:
extension FileSizeExtensions on num {
  /// method returns a human readable string representing a file size
  /// size can be passed as number or as string
  /// the optional parameter 'round' specifies the number of numbers after comma/point (default is 2)
  /// the optional boolean parameter 'useBase1024' specifies if we should count in 1024's (true) or 1000's (false). e.g. 1KB = 1024B (default is true)
  String toHumanReadableFileSize({int round = 2, bool useBase1024 = true}) {
    const List<String> affixes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'];

    num divider = useBase1024 ? 1024 : 1000;

    num size = this;
    num runningDivider = divider;
    num runningPreviousDivider = 0;
    int affix = 0;

    while (size >= runningDivider && affix < affixes.length - 1) {
      runningPreviousDivider = runningDivider;
      runningDivider *= divider;
      affix++;
    }

    String result = (runningPreviousDivider == 0 ? size : size / runningPreviousDivider).toStringAsFixed(round);

    //Check if the result ends with .00000 (depending on how many decimals) and remove it if found.
    if (result.endsWith("0" * round)) result = result.substring(0, result.length - round - 1);

    return "$result ${affixes[affix]}";
  }
}

示例输出:
1024 = 1 KB  
800 = 800 B  
8126 = 7.94 KB  
10247428 = 9.77 MB  

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接