Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

[Func] autoByteFormat - convert bytes to byte(s)/KB/MB/GB/TB


  • Please log in to reply
51 replies to this topic
animeaime
  • Members
  • 1045 posts
  • Last active: Jun 18 2011 04:44 AM
  • Joined: 04 Nov 2008
Functions: autoByteFormat

Description
[*:2derlw7z]Converts from a specified size (in byes) to an equivalent value in byte(s)/KB/MB/GB/TB - uses the most appropriate unit.
Download
autoByteFormat.zip

Requirements
AHK v1.0.48+



Functions
autoByteFormat(size, decimalPlaces = 2)
Converts from a specified size (in byes) to an equivalent value in byte(s)/KB/MB/GB/TB - uses the most appropriate unit.

See the wiki page for file size for details on what each of these units are. This function uses the "Binary Measurement" (see the conversion table for details).

Parameters
size - integer size (in bytes)
decimalPlaces - decimal places to round result. If return is in bytes, no rounding is done, since it's an integer.

ReturnValue
Formatted size in bytes(s)/KB/MB/GB/TB

Format:

if size = 1 (byte)
returns "1 byte"

else if size < 1KB (1024 bytes)
returns "X bytes"

else if size < 1MB (1024 * 1024 bytes)
returns "X KB"

else if size < 1GB (1024 * 1024 * 1024 bytes)
returns "X MB"

else if size < 1TB (1024 * 1024 * 1024 * 1024 bytes)
returns "X GB"

else
returns "X TB"

"X" is the rounded value (to the specified decimal places), in the appropriate units.

Remarks
Size MUST be greater than or equal to zero.



Code
;converts Size (in bytes) to byte(s)/KB/MB/GB/TB (uses best option)
;decimalPlaces is the number of decimal places to round
autoByteFormat(size, decimalPlaces = 2)
{
    static size1 = "KB", size2 = "MB", size3 = "GB", size4 = "TB"

    sizeIndex := 0

    while (size >= 1024)
    {
        sizeIndex++
        size /= 1024.0

        if (sizeIndex = 4)
            break
    }

    return (sizeIndex = 0) ? size " byte" . (size != 1 ? "s" : "")
        : round(size, decimalPlaces) . " " . size%sizeIndex%
}

Example
1MB := 1024 * 1024
1@26MB := 1.26 * 1024 * 1024
1000@27GB := 1000.27 * 1024 * 1024 * 1024
17@28TB := 17.28 * 1024 * 1024 * 1024 * 1024

Bytes =
(LTrim
    0
    1
    2
    100
    1024
    1500
    %1MB%
    %1@26MB%
    %1000@27GB%
    %17@28TB%
)

Loop, Parse, Bytes, `n
{
    MsgBox, % A_LoopField " bytes = " autoByteFormat(A_LoopField)
}



How to use
Extract the zip's contents to a library folder for automatic inclusion - StdLib compliant.

A copy of the above example can be found in the "Func Examples" folder.


Download autoByteFormat function

Laszlo
  • Moderators
  • 4713 posts
  • Last active: Mar 31 2012 03:17 AM
  • Joined: 14 Feb 2005
Thanks for posting this. You probably know it already that MB, GB and TB means 1e6, 1e9 and 1e12 bytes, respectively, if disk manufacturers use them to specify the capacity of their drives, so there will be always some confusions.

animeaime
  • Members
  • 1045 posts
  • Last active: Jun 18 2011 04:44 AM
  • Joined: 04 Nov 2008
I used KB, MB, GB, and TB as they are commonly defined (like shown in the file's properties)

e.g.
1KB = 1024 bytes.

Hopefully, this doesn't cause too much confusion. I'll add a link to the wiki page for file size to shed light where otherwise might have been confusion. Thanks for the heads up.

SKAN
  • Administrators
  • 9105 posts
  • Last active:
  • Joined: 26 Dec 2005
There is an API function for this: StrFormatByteSize64, but I guess the function is limited to GB.
A working example can be found here.

  • Guests
  • Last active:
  • Joined: --
You should stop requiring readers to download a zip file from your account on autohotkey.net (or anywhere else for that matter).

There are three reasons I say this.

First, I have noticed that several of your functions are only a couple of hundred bytes long. There is no reason to not post it in the forum, so readers can look at the code without having to download and unpack.

Second, by posting the code in the forum, readers can see when the topic/code was last edited (alerting the reader to an update/change).

Third, your account on autohotkey.net will not be maintained forever (as will posting in the forum). If your account becomes inactive for a long period of time, I believe that the account (and its contents will be deleted). I know that after not having accessed my account for about a year, I was sent a notice that if I did not login, my account would be deleted. So, if (and when) you move on, the linked downloads may not be available.

Finally (and this is just my personal reaction). After having downloaded several of your short functions, I am now not inclined to download and examine the zip files if the function (as in this case) seems to me to be 'trivial' and hardly worth the time to examine (maybe my loss). Whereas if the code is posted, I am more likely to examine it and then decide if it is worth keeping.

This topic of posting/downloading has come up in the forum before (although I cannot locate it now), and if I recall correctly, most readers that replied to the topic prefered that the code be posted.

Thanks for reading this.

polyethene
  • Administrators
  • 5511 posts
  • Last active: Yesterday, 11:38 PM
  • Joined: 26 Oct 2012

your account on autohotkey.net will not be maintained forever (as will posting in the forum). If your account becomes inactive for a long period of time, I believe that the account (and its contents will be deleted). I know that after not having accessed my account for about a year, I was sent a notice that if I did not login, my account would be deleted. So, if (and when) you move on, the linked downloads may not be available.

I was notified about this so I will respond here. What you have said is untrue and misleading. Newly created accounts with no activity (logins, uploads or downloads) are flagged then removed after a month. The mass email sent a while ago requested users who had not used the new web manager to log in so their database profile could be automatically transferred. If you could read properly you would have known this. The account removal only applied under the said circumstance. Get your facts straight before posting next time.

animeaime
  • Members
  • 1045 posts
  • Last active: Jun 18 2011 04:44 AM
  • Joined: 04 Nov 2008

There is no reason to not post it in the forum, so readers can look at the code without having to download and unpack.

Thank you for your input. I was trying to be "neat", but I see your point. I'll post the code on all my topics (both future and existing ones). Thank you for your feedback.


Second, by posting the code in the forum, readers can see when the topic/code was last edited (alerting the reader to an update/change).

If I update my code, I'll make a quick post. This allows anyone that watches the thread to be able to download the latest version.

Finally (and this is just my personal reaction). After having downloaded several of your short functions, I am now not inclined to download and examine the zip files if the function (as in this case) seems to me to be 'trivial' and hardly worth the time to examine (maybe my loss). Whereas if the code is posted, I am more likely to examine it and then decide if it is worth keeping.

I know exactly how you feel - truthfully, I felt ashamed posting these. They are short, and not anything "amazing". I posted them, because they are functions that I think should be "standardized". Additionally, I'm going to be posting some scripts that make use of some of these "nicknacks", so I wanted to post them, and get feedback, before posting the scripts. This way, I could get valuable feedback, and make necessary adjustments.

animeaime
  • Members
  • 1045 posts
  • Last active: Jun 18 2011 04:44 AM
  • Joined: 04 Nov 2008

There is an API function for this: StrFormatByteSize64, but I guess the function is limited to GB.
A working example can be found here.

Thanks for brining up this function, I was not aware of it. Is there a way to control the number of decimal places it rounds to?

Edit:
What do you mean it only works for GB? The API function has other examples as well.

SKAN
  • Administrators
  • 9105 posts
  • Last active:
  • Joined: 26 Dec 2005

What do you mean it only works for GB? The API function has other examples as well.


I had thought the function would not work for bytes exceeding GB. I was wrong!

Bytes := [color=red]9223372036854775807[/color],   VarSetCapacity( Formatted,24,0 )
DllCall( "shlwapi.dll\StrFormatByteSize64A", Int64,Bytes, Str,Formatted, UInt,16 )
MsgBox, % Formatted


Laszlo
  • Moderators
  • 4713 posts
  • Last active: Mar 31 2012 03:17 AM
  • Joined: 14 Feb 2005
StrFormatByteSize... seems to round the result to only 3 digits, which are sometimes too few.

animeaime
  • Members
  • 1045 posts
  • Last active: Jun 18 2011 04:44 AM
  • Joined: 04 Nov 2008
Also, for some odd reason, an example they gave isn't the rounded result, and it only has one digit of precision.

Bytes := 23506,   VarSetCapacity( Formatted,24,0 )
DllCall( "shlwapi.dll\StrFormatByteSize64A", "Int64",Bytes, "Str",Formatted, "UInt",16 )

;outputs 22.9 KB
MsgBox, % Formatted

;outputs 22.96 KB
MsgBox, % autoByteFormat(bytes)


TheGood
  • Members
  • 589 posts
  • Last active: Mar 22 2014 03:22 PM
  • Joined: 30 Jul 2007

I used KB, MB, GB, and TB as they are properly defined (like shown in the file's properties)


As Lazslo said, KB, MB, etc... are officially defined as SI units by which KB means 1000^1 bytes, MB means 1000^2 bytes, etc...
Some organizations have been pushing for the use of the term "kibibyte", "mibibyte", etc... to mean 1024^1, 1024^2, etc... but it's not exactly catching on.
Anyways, just wanted to let you know that, although a lot of programs (like Windows) use the binary definition, it officially isn't so.
Unfortunately, this confusion has caused many problems to consumers (as well as lawsuits against some companies, like Seagate).

animeaime
  • Members
  • 1045 posts
  • Last active: Jun 18 2011 04:44 AM
  • Joined: 04 Nov 2008
I know this may sound rude, and I appoligize before saying it. Since it can cause confusion, I'm not sure what to do then. Do you have a recommendation?

Would removing the phrase "properly defined" do the job :D? I realize this can be confusing, and I want to clear up that confusion.

The function uses the measurement I've seen used in every program I've used (including windows itself). I mean, the StrFormatByteSize function that SKAN pointed out uses the same format.

So, I'm at a loss. Truthfully, at this point, I'm confused about who is confused. The ONLY time I have ever heard the decimal usage of GB is by the makers of hard drives to save some of their money. I mean, every program, even Windows, uses the binary, but still the hard drive manufactures want to "claim" my computer with 160 024 174 592 bytes between it's four partions is a 160GB hard drive when every program says that all I have is autoByteFormat(160 024 174 592) = 149.03 GB.

Krogdor
  • Members
  • 1391 posts
  • Last active: Jun 08 2011 05:31 AM
  • Joined: 18 Apr 2008
animeaime, although that definition is the most commonly used, the Wikipedia article clearly states that for the powers of two definition, the proper prefix is Ki, Mi, Gi, etc. rather than K, M, G, etc. because those prefixes are used to denote powers of ten. However, the article is a bit contradictory, since the conversion table states the binary definition for the Kilo, Mega, Giga, etc prefixes...

In my opinion, the binary definition is definitely the one that should be used in this function, and you have clearly stated that you have used it, so I think you have done everything correctly.

Would removing the phrase "properly defined" do the job Very Happy? I realize this can be confusing, and I want to clear up that confusion.


I think changing "properly defined" to "commonly defined" would fit better.

animeaime
  • Members
  • 1045 posts
  • Last active: Jun 18 2011 04:44 AM
  • Joined: 04 Nov 2008
Thank you all for your input on this matter - the function will remain as it is.

I changed "properly defined" to "commonly defined" as suggested by Krogdor.