Làm cách nào để có được kích thước tệp có thể đọc được bằng chữ viết tắt byte bằng .NET?
Ví dụ : Lấy đầu vào 7.326.629 và hiển thị 6,98 MB
Làm cách nào để có được kích thước tệp có thể đọc được bằng chữ viết tắt byte bằng .NET?
Ví dụ : Lấy đầu vào 7.326.629 và hiển thị 6,98 MB
Câu trả lời:
Đây không phải là cách hiệu quả nhất để làm điều đó, nhưng nó dễ đọc hơn nếu bạn không quen thuộc với toán học nhật ký và phải đủ nhanh cho hầu hết các kịch bản.
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
sử dụng Log để giải quyết vấn đề ....
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ũng trong c #, nhưng nên nhanh chóng chuyển đổi. Ngoài ra tôi làm tròn đến 1 chữ số thập phân để dễ đọc.
Về cơ bản Xác định số lượng vị trí thập phân trong Cơ sở 1024 và sau đó chia cho 1024 ^ số thập phân.
Và một số mẫu sử dụng và đầu ra:
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
Chỉnh sửa: Đã chỉ ra rằng tôi đã bỏ lỡ một math.floor, vì vậy tôi kết hợp nó. (Convert.ToInt32 sử dụng làm tròn, không cắt ngắn và đó là lý do tại sao Tầng là cần thiết.) Cảm ơn bạn đã nắm bắt.
Edit2: Có một vài ý kiến về kích thước âm và kích thước 0 byte, vì vậy tôi đã cập nhật để xử lý 2 trường hợp đó.
double.MaxValue
(nơi = 102)
Một phiên bản thử nghiệm và tối ưu hóa đáng kể của chức năng được yêu cầu được đăng ở đây:
Kích thước tệp có thể đọc được của con người C # - Chức năng được tối ưu hóa
Mã nguồn:
// 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);
bất cứ đâu để loại bỏ nó. một điều nữa, dàn diễn viên là 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();
}
Từ: http://www.pinvoke.net/default.aspx/shlwapi/StrFormatByteSize.html
Một cách nữa để tạo ra nó, không có bất kỳ loại vòng lặp nào và với sự hỗ trợ kích thước âm (có ý nghĩa đối với những thứ như deltas kích thước tệp):
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]);
}
}
Và đây là bộ thử nghiệm:
[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);
}
}
Kiểm tra thư viện ByteSize . Đó là System.TimeSpan
cho byte!
Nó xử lý việc chuyển đổi và định dạng cho bạn.
var maxFileSize = ByteSize.FromKiloBytes(10);
maxFileSize.Bytes;
maxFileSize.MegaBytes;
maxFileSize.GigaBytes;
Nó cũng không đại diện chuỗi và phân tích cú pháp.
// 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");
Tôi thích sử dụng phương pháp sau (nó hỗ trợ tối đa terabyte, đủ cho hầu hết các trường hợp, nhưng nó có thể dễ dàng được mở rộng):
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}";
}
Xin lưu ý rằng điều này được viết cho C # 6.0 (2015), vì vậy nó có thể cần một chút chỉnh sửa cho các phiên bản trước.
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
hoặc một cái gì đó.
Đây là một câu trả lời ngắn gọn xác định đơn vị tự động.
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" là cho bit, "B" là dành cho Byte và "KMGTPEZY" tương ứng cho kilo, mega, giga, tera, peta, exa, zetta và yotta
Người ta có thể mở rộng nó để đưa ISO / IEC80000 vào tài khoản:
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
sau KMGTPE: tiếng Pháp của nó ( byte
là octet
tiếng Pháp). Đối với bất kỳ ngôn ngữ nào khác, chỉ cần thay thế o
bằngb
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]);
Nếu bạn đang cố gắng khớp kích thước như trong chế độ xem chi tiết của Windows Explorer, đây là mã bạn muốn:
[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();
}
Điều này sẽ không chỉ khớp chính xác với Explorer mà còn cung cấp các chuỗi được dịch cho bạn và khớp các khác biệt trong các phiên bản Windows (ví dụ: trong Win10, K = 1000 so với các phiên bản trước K = 1024).
Hỗn hợp của tất cả các giải pháp :-)
/// <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
}
Có một dự án nguồn mở có thể làm điều đó và hơn thế nữa.
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
Giống như giải pháp của @ NET3. Sử dụng shift thay vì chia để kiểm tra phạm vi bytes
, bởi vì phân chia tốn nhiều chi phí CPU hơn.
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]);
}
Tôi giả sử bạn đang tìm kiếm "1,4 MB" thay vì "1468006 byte"?
Tôi không nghĩ rằng có một cách tích hợp để làm điều đó trong .NET. Bạn sẽ cần chỉ ra đơn vị nào là phù hợp và định dạng nó.
Chỉnh sửa: Đây là một số mã mẫu để làm điều đó:
Làm thế nào về một số đệ quy:
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");
}
}
Sau đó, bạn gọi nó:
return ReturnSize(size, string.Empty);
2 xu của tôi:
string.Format(CultureInfo.CurrentCulture, "{0:0.##} {1}", fileSize, unit);
Một cách tiếp cận nữa, cho những gì nó có giá trị. Tôi thích giải pháp tối ưu hóa @humbads được tham chiếu ở trên, vì vậy đã sao chép nguyên tắc này, nhưng tôi đã thực hiện nó một chút khác biệt.
Tôi cho rằng nó có thể gây tranh cãi về việc liệu nó có phải là một phương thức mở rộng hay không (vì không phải tất cả các độ dài đều nhất thiết phải là kích thước byte), nhưng tôi thích chúng, và ở đâu đó tôi có thể tìm thấy phương thức khi tôi cần tiếp theo!
Về các đơn vị, tôi không nghĩ rằng mình đã từng nói 'Kibibyte' hay 'Mebibyte' trong cuộc sống của mình, và trong khi tôi nghi ngờ về các tiêu chuẩn được thi hành như vậy hơn là phát triển, tôi cho rằng về lâu dài sẽ tránh nhầm lẫn .
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);
}
}
Tôi sử dụng phương pháp mở rộng dài bên dưới để chuyển đổi thành chuỗi kích thước có thể đọc được của con người. Phương pháp này là triển khai C # của giải pháp Java cho cùng một câu hỏi được đăng trên Stack Overflow, tại đây .
/// <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";
}