如何实现Windows属性面板风格的文件大小格式化PowerShell函数?
实现Windows资源管理器风格的文件大小格式化PowerShell函数
问题描述
我想在PowerShell中实现类似C++ SizeOf()的功能,但发现Windows计算MiB(mebibyte)的算法比较特殊:
- 创建1,856,000字节的文件,Windows属性面板显示「1,76 MB (1.856.000 bytes)」
- 创建1,857,000字节的文件,属性面板显示「1,77 MB (1.857.000 bytes)」
- 对于1,900,738,660字节的文件,系统显示「1,76 GB (1.900.738.660 bytes)」
但我自己写的脚本会把1,900,738,660字节向上取整为1.77 GB(因为1900738660 ÷ 1073741824 ≈ 1.7702),对前面的MB文件也统一显示1.77 MB,想知道explorer.exe将字节转换为KiB/MiB/GiB的公式是什么?
解决方法
通过调用Windows系统Shlwapi.dll中的StrFormatByteSize函数,可以完全复刻Windows资源管理器的文件大小格式化逻辑。以下是最终实现的PowerShell函数:
<# .SYNOPSIS 获取Windows风格的大小格式 .DESCRIPTION 将文件或整数大小格式化为Windows属性面板「常规>大小」的样式(例如:0 bytes (0 bytes)),支持管道输入 .PARAMETER FileOrBytes 要格式化的文件路径或整数大小!!! .EXAMPLE SizeOF "C:\somefile.txt" SizeOF 1234 返回值: 1,20 KB (1.234 bytes) .NOTES 通用说明 #> $Shlwapi = Add-Type -MemberDefinition ' [DllImport("Shlwapi.dll", CharSet=CharSet.Auto)]public static extern int StrFormatByteSize(long fileSize, System.Text.StringBuilder pwszBuff, int cchBuff); ' -Name "ShlwapiFunctions" -namespace ShlwapiFunctions -PassThru function SizeOF { param([parameter(Mandatory = $true, ValueFromPipeline = $true)] [ValidateNotNullOrEmpty()] [System.Object]$FileOrBytes ) if (@([System.UInt16], [System.Int16], [System.UInt32], [System.Int32], [System.UInt64], [System.Int64]) -contains $FileOrBytes.GetType()) { [int64]$Size = $FileOrBytes } elseif ($FileOrBytes -is [System.String]) { try { [int64]$Size = (Get-ChildItem -LiteralPath $FileOrBytes -Hidden -ErrorAction Stop).Length } catch { return -1 } } if ($Size -eq 0) { return [System.String]$Size + " bytes" } $Bytes = New-Object Text.StringBuilder 20 $Return = $Shlwapi::StrFormatByteSize($Size, $Bytes, $Bytes.Capacity) if ($Return) { if ($Size -lt 10) { return $Bytes.ToString() + " ($($Bytes.ToString()))" } return $Bytes.ToString() + " ($($Size.ToString("0,0")) bytes)" } return -1 }
内容的提问来源于stack exchange,提问作者EverGreen
相关产品推荐
相关产品推荐

