ฉันจะรับขนาดไฟล์ที่มนุษย์สามารถอ่านได้เป็นตัวย่อไบต์โดยใช้. NET
ตัวอย่าง : ใช้อินพุต 7,326,629 และแสดง 6.98 MB
ฉันจะรับขนาดไฟล์ที่มนุษย์สามารถอ่านได้เป็นตัวย่อไบต์โดยใช้. NET
ตัวอย่าง : ใช้อินพุต 7,326,629 และแสดง 6.98 MB
คำตอบ:
นี่ไม่ใช่วิธีที่มีประสิทธิภาพที่สุดในการทำ แต่อ่านง่ายขึ้นถ้าคุณไม่คุ้นเคยกับ log maths และควรเร็วพอสำหรับสถานการณ์ส่วนใหญ่
string[] sizes = { "B", "KB", "MB", "GB", "TB" };
double len = new FileInfo(filename).Length;
int order = 0;
while (len >= 1024 && order < sizes.Length - 1) {
order++;
len = len/1024;
}
// Adjust the format string to your preferences. For example "{0:0.#}{1}" would
// show a single decimal place, and no space.
string result = String.Format("{0:0.##} {1}", len, sizes[order]);
The unit was established by the International Electrotechnical Commission (IEC) in 1998 and has been accepted for use by all major standards organizations
ใช้บันทึกเพื่อแก้ปัญหา ....
static String BytesToString(long byteCount)
{
string[] suf = { "B", "KB", "MB", "GB", "TB", "PB", "EB" }; //Longs run out around EB
if (byteCount == 0)
return "0" + suf[0];
long bytes = Math.Abs(byteCount);
int place = Convert.ToInt32(Math.Floor(Math.Log(bytes, 1024)));
double num = Math.Round(bytes / Math.Pow(1024, place), 1);
return (Math.Sign(byteCount) * num).ToString() + suf[place];
}
นอกจากนี้ใน c # แต่ควรเป็นสแนปเพื่อแปลง อีกทั้งฉันปัดเศษทศนิยม 1 ตำแหน่งเพื่อให้สามารถอ่านได้
กำหนดจำนวนตำแหน่งทศนิยมใน 1024 ฐานโดยทั่วไปแล้วหารด้วย 1024 ^ ทศนิยม
และตัวอย่างบางส่วนของการใช้งานและเอาท์พุท:
Console.WriteLine(BytesToString(9223372036854775807)); //Results in 8EB
Console.WriteLine(BytesToString(0)); //Results in 0B
Console.WriteLine(BytesToString(1024)); //Results in 1KB
Console.WriteLine(BytesToString(2000000)); //Results in 1.9MB
Console.WriteLine(BytesToString(-9023372036854775807)); //Results in -7.8EB
แก้ไข: ถูกชี้ให้เห็นว่าฉันพลาด math.floor ดังนั้นฉันจึงรวมเข้าด้วยกัน (Convert.ToInt32 ใช้การปัดเศษไม่ใช่การตัดทอนและนั่นเป็นเหตุผลว่าทำไม Floor จึงจำเป็น) ขอบคุณสำหรับการจับ
แก้ไข 2: มีความคิดเห็นสองสามข้อเกี่ยวกับขนาดเชิงลบและขนาด 0 ไบต์ดังนั้นฉันจึงอัปเดตเพื่อจัดการ 2 กรณีเหล่านั้น
double.MaxValue
(สถานที่ = 102)
รุ่นที่ได้รับการทดสอบและปรับให้เหมาะสมอย่างมากของฟังก์ชั่นที่ร้องขอถูกโพสต์ที่นี่:
ขนาดไฟล์ C # ที่มนุษย์อ่านได้ - ฟังก์ชันที่ปรับให้เหมาะสม
รหัสแหล่งที่มา:
// Returns the human-readable file size for an arbitrary, 64-bit file size
// The default format is "0.### XB", e.g. "4.2 KB" or "1.434 GB"
public string GetBytesReadable(long i)
{
// Get absolute value
long absolute_i = (i < 0 ? -i : i);
// Determine the suffix and readable value
string suffix;
double readable;
if (absolute_i >= 0x1000000000000000) // Exabyte
{
suffix = "EB";
readable = (i >> 50);
}
else if (absolute_i >= 0x4000000000000) // Petabyte
{
suffix = "PB";
readable = (i >> 40);
}
else if (absolute_i >= 0x10000000000) // Terabyte
{
suffix = "TB";
readable = (i >> 30);
}
else if (absolute_i >= 0x40000000) // Gigabyte
{
suffix = "GB";
readable = (i >> 20);
}
else if (absolute_i >= 0x100000) // Megabyte
{
suffix = "MB";
readable = (i >> 10);
}
else if (absolute_i >= 0x400) // Kilobyte
{
suffix = "KB";
readable = i;
}
else
{
return i.ToString("0 B"); // Byte
}
// Divide by 1024 to get fractional value
readable = (readable / 1024);
// Return formatted number with suffix
return readable.ToString("0.### ") + suffix;
}
double readable = (i < 0 ? -i : i);
ที่ใด ๆ ดังนั้นให้ลบออก อีกสิ่งหนึ่งนักแสดงคือ redaundat
Math.Abs
?
[DllImport ( "Shlwapi.dll", CharSet = CharSet.Auto )]
public static extern long StrFormatByteSize (
long fileSize
, [MarshalAs ( UnmanagedType.LPTStr )] StringBuilder buffer
, int bufferSize );
/// <summary>
/// Converts a numeric value into a string that represents the number expressed as a size value in bytes, kilobytes, megabytes, or gigabytes, depending on the size.
/// </summary>
/// <param name="filelength">The numeric value to be converted.</param>
/// <returns>the converted string</returns>
public static string StrFormatByteSize (long filesize) {
StringBuilder sb = new StringBuilder( 11 );
StrFormatByteSize( filesize, sb, sb.Capacity );
return sb.ToString();
}
จาก: http://www.pinvoke.net/default.aspx/shlwapi/StrFormatByteSize.html
อีกวิธีหนึ่งในการสกินโดยไม่มีลูปใด ๆ และด้วยการรองรับขนาดลบ (ทำให้รู้สึกถึงสิ่งต่าง ๆ เช่นเดลต้าขนาดไฟล์):
public static class Format
{
static string[] sizeSuffixes = {
"B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" };
public static string ByteSize(long size)
{
Debug.Assert(sizeSuffixes.Length > 0);
const string formatTemplate = "{0}{1:0.#} {2}";
if (size == 0)
{
return string.Format(formatTemplate, null, 0, sizeSuffixes[0]);
}
var absSize = Math.Abs((double)size);
var fpPower = Math.Log(absSize, 1000);
var intPower = (int)fpPower;
var iUnit = intPower >= sizeSuffixes.Length
? sizeSuffixes.Length - 1
: intPower;
var normSize = absSize / Math.Pow(1000, iUnit);
return string.Format(
formatTemplate,
size < 0 ? "-" : null, normSize, sizeSuffixes[iUnit]);
}
}
และนี่คือชุดทดสอบ:
[TestFixture] public class ByteSize
{
[TestCase(0, Result="0 B")]
[TestCase(1, Result = "1 B")]
[TestCase(1000, Result = "1 KB")]
[TestCase(1500000, Result = "1.5 MB")]
[TestCase(-1000, Result = "-1 KB")]
[TestCase(int.MaxValue, Result = "2.1 GB")]
[TestCase(int.MinValue, Result = "-2.1 GB")]
[TestCase(long.MaxValue, Result = "9.2 EB")]
[TestCase(long.MinValue, Result = "-9.2 EB")]
public string Format_byte_size(long size)
{
return Format.ByteSize(size);
}
}
ชำระเงินห้องสมุดByteSize มันคือจำนวนSystem.TimeSpan
ไบต์!
มันจัดการการแปลงและการจัดรูปแบบสำหรับคุณ
var maxFileSize = ByteSize.FromKiloBytes(10);
maxFileSize.Bytes;
maxFileSize.MegaBytes;
maxFileSize.GigaBytes;
มันยังทำหน้าที่เป็นตัวแทนสตริงและแยก
// ToString
ByteSize.FromKiloBytes(1024).ToString(); // 1 MB
ByteSize.FromGigabytes(.5).ToString(); // 512 MB
ByteSize.FromGigabytes(1024).ToString(); // 1 TB
// Parsing
ByteSize.Parse("5b");
ByteSize.Parse("1.55B");
ฉันชอบใช้วิธีการต่อไปนี้ (รองรับสูงสุดเทราไบต์ซึ่งเพียงพอสำหรับกรณีส่วนใหญ่ แต่สามารถขยายได้อย่างง่ายดาย):
private string GetSizeString(long length)
{
long B = 0, KB = 1024, MB = KB * 1024, GB = MB * 1024, TB = GB * 1024;
double size = length;
string suffix = nameof(B);
if (length >= TB) {
size = Math.Round((double)length / TB, 2);
suffix = nameof(TB);
}
else if (length >= GB) {
size = Math.Round((double)length / GB, 2);
suffix = nameof(GB);
}
else if (length >= MB) {
size = Math.Round((double)length / MB, 2);
suffix = nameof(MB);
}
else if (length >= KB) {
size = Math.Round((double)length / KB, 2);
suffix = nameof(KB);
}
return $"{size} {suffix}";
}
โปรดทราบว่าสิ่งนี้เขียนขึ้นสำหรับ C # 6.0 (2015) ดังนั้นอาจต้องแก้ไขเล็กน้อยสำหรับเวอร์ชันก่อนหน้า
int size = new FileInfo( filePath ).Length / 1024;
string humanKBSize = string.Format( "{0} KB", size );
string humanMBSize = string.Format( "{0} MB", size / 1024 );
string humanGBSize = string.Format( "{0} GB", size / 1024 / 1024 );
Math.Ceiling
หรือเศษส่วน
นี่คือคำตอบสั้น ๆ ที่กำหนดหน่วยโดยอัตโนมัติ
public static string ToBytesCount(this long bytes)
{
int unit = 1024;
string unitStr = "b";
if (bytes < unit) return string.Format("{0} {1}", bytes, unitStr);
else unitStr = unitStr.ToUpper();
int exp = (int)(Math.Log(bytes) / Math.Log(unit));
return string.Format("{0:##.##} {1}{2}", bytes / Math.Pow(unit, exp), "KMGTPEZY"[exp - 1], unitStr);
}
"b" สำหรับบิต "B" สำหรับ Byte และ "KMGTPEZY" เป็นลำดับสำหรับกิโล, เมกะ, giga, tera, peta, exa, zetta และ yotta
หนึ่งสามารถขยายเพื่อนำISO / IEC80000เข้าบัญชี:
public static string ToBytesCount(this long bytes, bool isISO = true)
{
int unit = 1024;
string unitStr = "b";
if (!isISO) unit = 1000;
if (bytes < unit) return string.Format("{0} {1}", bytes, unitStr);
else unitStr = unitStr.ToUpper();
if (isISO) unitStr = "i" + unitStr;
int exp = (int)(Math.Log(bytes) / Math.Log(unit));
return string.Format("{0:##.##} {1}{2}", bytes / Math.Pow(unit, exp), "KMGTPEZY"[exp - 1], unitStr);
}
o
KMGTPE ถึงเกิดขึ้นหลังจากนั้น: ภาษาฝรั่งเศส ( byte
เป็นoctet
ภาษาฝรั่งเศส) สำหรับภาษาอื่น ๆ ให้แทนที่o
ด้วยb
string[] suffixes = { "B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" };
int s = 0;
long size = fileInfo.Length;
while (size >= 1024)
{
s++;
size /= 1024;
}
string humanReadable = String.Format("{0} {1}", size, suffixes[s]);
หากคุณพยายามจับคู่ขนาดตามที่แสดงในมุมมองรายละเอียดของ Windows Explorer นี่คือรหัสที่คุณต้องการ:
[DllImport("shlwapi.dll", CharSet = CharSet.Unicode)]
private static extern long StrFormatKBSize(
long qdw,
[MarshalAs(UnmanagedType.LPTStr)] StringBuilder pszBuf,
int cchBuf);
public static string BytesToString(long byteCount)
{
var sb = new StringBuilder(32);
StrFormatKBSize(byteCount, sb, sb.Capacity);
return sb.ToString();
}
สิ่งนี้จะไม่เพียงตรงกับ Explorer อย่างแน่นอน แต่จะให้สตริงที่แปลสำหรับคุณและตรงกับความแตกต่างในรุ่น Windows (เช่นใน Win10, K = 1000 เทียบกับรุ่นก่อนหน้า K = 1024)
ส่วนผสมของโซลูชั่นทั้งหมด :-)
/// <summary>
/// Converts a numeric value into a string that represents the number expressed as a size value in bytes,
/// kilobytes, megabytes, or gigabytes, depending on the size.
/// </summary>
/// <param name="fileSize">The numeric value to be converted.</param>
/// <returns>The converted string.</returns>
public static string FormatByteSize(double fileSize)
{
FileSizeUnit unit = FileSizeUnit.B;
while (fileSize >= 1024 && unit < FileSizeUnit.YB)
{
fileSize = fileSize / 1024;
unit++;
}
return string.Format("{0:0.##} {1}", fileSize, unit);
}
/// <summary>
/// Converts a numeric value into a string that represents the number expressed as a size value in bytes,
/// kilobytes, megabytes, or gigabytes, depending on the size.
/// </summary>
/// <param name="fileInfo"></param>
/// <returns>The converted string.</returns>
public static string FormatByteSize(FileInfo fileInfo)
{
return FormatByteSize(fileInfo.Length);
}
}
public enum FileSizeUnit : byte
{
B,
KB,
MB,
GB,
TB,
PB,
EB,
ZB,
YB
}
มีโครงการโอเพ่นซอร์สหนึ่งโครงการที่สามารถทำสิ่งนั้นได้และอีกมากมาย
7.Bits().ToString(); // 7 b
8.Bits().ToString(); // 1 B
(.5).Kilobytes().Humanize(); // 512 B
(1000).Kilobytes().ToString(); // 1000 KB
(1024).Kilobytes().Humanize(); // 1 MB
(.5).Gigabytes().Humanize(); // 512 MB
(1024).Gigabytes().ToString(); // 1 TB
ชอบวิธีแก้ปัญหาของ @ NET3 ใช้ shift แทนการหารเพื่อทดสอบช่วงbytes
เนื่องจากการแบ่งใช้ต้นทุน CPU มากขึ้น
private static readonly string[] UNITS = new string[] { "B", "KB", "MB", "GB", "TB", "PB", "EB" };
public static string FormatSize(ulong bytes)
{
int c = 0;
for (c = 0; c < UNITS.Length; c++)
{
ulong m = (ulong)1 << ((c + 1) * 10);
if (bytes < m)
break;
}
double n = bytes / (double)((ulong)1 << (c * 10));
return string.Format("{0:0.##} {1}", n, UNITS[c]);
}
ฉันถือว่าคุณกำลังมองหา "1.4 MB" แทนที่จะเป็น "1468006 bytes"?
ฉันไม่คิดว่าจะมีวิธีการดังกล่าวในตัวใน. NET คุณจะต้องคิดออกว่าหน่วยใดเหมาะสมและจัดรูปแบบ
แก้ไข: นี่คือตัวอย่างรหัสที่จะทำเช่นนั้น:
เกี่ยวกับการสอบถามซ้ำ:
private static string ReturnSize(double size, string sizeLabel)
{
if (size > 1024)
{
if (sizeLabel.Length == 0)
return ReturnSize(size / 1024, "KB");
else if (sizeLabel == "KB")
return ReturnSize(size / 1024, "MB");
else if (sizeLabel == "MB")
return ReturnSize(size / 1024, "GB");
else if (sizeLabel == "GB")
return ReturnSize(size / 1024, "TB");
else
return ReturnSize(size / 1024, "PB");
}
else
{
if (sizeLabel.Length > 0)
return string.Concat(size.ToString("0.00"), sizeLabel);
else
return string.Concat(size.ToString("0.00"), "Bytes");
}
}
จากนั้นคุณเรียกมันว่า:
return ReturnSize(size, string.Empty);
2 เซนต์ของฉัน:
string.Format(CultureInfo.CurrentCulture, "{0:0.##} {1}", fileSize, unit);
อีกวิธีหนึ่งสำหรับสิ่งที่คุ้มค่า ฉันชอบ @humbads วิธีการแก้ปัญหาที่เพิ่มประสิทธิภาพการอ้างอิงข้างต้นดังนั้นได้คัดลอกหลักการ แต่ฉันใช้มันแตกต่างกันเล็กน้อย
ฉันคิดว่ามันเป็นที่ถกเถียงกันอยู่ว่าควรจะเป็นวิธีการต่อขยายหรือไม่ (เนื่องจากความยาวทั้งหมดไม่จำเป็นต้องเป็นขนาดไบต์) แต่ฉันชอบพวกเขาและเป็นที่ที่ฉันสามารถหาวิธีได้เมื่อฉันต้องการมันต่อไป!
เกี่ยวกับหน่วยฉันไม่คิดว่าฉันเคยพูดว่า 'Kibibyte' หรือ 'Mebibyte' ในชีวิตของฉันและในขณะที่ฉันไม่แน่ใจว่ามีการบังคับใช้ดังกล่าวมากกว่ามาตรฐานที่พัฒนาแล้วฉันคิดว่ามันจะหลีกเลี่ยงความสับสนในระยะยาว .
public static class LongExtensions
{
private static readonly long[] numberOfBytesInUnit;
private static readonly Func<long, string>[] bytesToUnitConverters;
static LongExtensions()
{
numberOfBytesInUnit = new long[6]
{
1L << 10, // Bytes in a Kibibyte
1L << 20, // Bytes in a Mebibyte
1L << 30, // Bytes in a Gibibyte
1L << 40, // Bytes in a Tebibyte
1L << 50, // Bytes in a Pebibyte
1L << 60 // Bytes in a Exbibyte
};
// Shift the long (integer) down to 1024 times its number of units, convert to a double (real number),
// then divide to get the final number of units (units will be in the range 1 to 1023.999)
Func<long, int, string> FormatAsProportionOfUnit = (bytes, shift) => (((double)(bytes >> shift)) / 1024).ToString("0.###");
bytesToUnitConverters = new Func<long,string>[7]
{
bytes => bytes.ToString() + " B",
bytes => FormatAsProportionOfUnit(bytes, 0) + " KiB",
bytes => FormatAsProportionOfUnit(bytes, 10) + " MiB",
bytes => FormatAsProportionOfUnit(bytes, 20) + " GiB",
bytes => FormatAsProportionOfUnit(bytes, 30) + " TiB",
bytes => FormatAsProportionOfUnit(bytes, 40) + " PiB",
bytes => FormatAsProportionOfUnit(bytes, 50) + " EiB",
};
}
public static string ToReadableByteSizeString(this long bytes)
{
if (bytes < 0)
return "-" + Math.Abs(bytes).ToReadableByteSizeString();
int counter = 0;
while (counter < numberOfBytesInUnit.Length)
{
if (bytes < numberOfBytesInUnit[counter])
return bytesToUnitConverters[counter](bytes);
counter++;
}
return bytesToUnitConverters[counter](bytes);
}
}
ฉันใช้วิธีการขยายแบบยาวด้านล่างเพื่อแปลงเป็นสตริงขนาดที่มนุษย์อ่านได้ วิธีนี้เป็นวิธีการดำเนินงาน C # ของการแก้ปัญหาของ Java คำถามเดียวกันนี้โพสต์บนกองมากเกิน, ที่นี่
/// <summary>
/// Convert a byte count into a human readable size string.
/// </summary>
/// <param name="bytes">The byte count.</param>
/// <param name="si">Whether or not to use SI units.</param>
/// <returns>A human readable size string.</returns>
public static string ToHumanReadableByteCount(
this long bytes
, bool si
)
{
var unit = si
? 1000
: 1024;
if (bytes < unit)
{
return $"{bytes} B";
}
var exp = (int) (Math.Log(bytes) / Math.Log(unit));
return $"{bytes / Math.Pow(unit, exp):F2} " +
$"{(si ? "kMGTPE" : "KMGTPE")[exp - 1] + (si ? string.Empty : "i")}B";
}