Click here to Skip to main content
16,004,406 members
Articles / Desktop Programming / MFC
Article

Format File Sizes in Human Readable Format

Rate me:
Please Sign up or sign in to vote.
1.89/5 (6 votes)
30 Nov 20021 min read 106.1K   981   25   17
An article on formatting of file sizes in a human readable format.

Format Size Test Application

Introduction

While working on a project I needed to display the sizes in a human readable format, i.e. 1KB, 1.20MB, and so on. Although I am referring to this functionality here as file size formatting, the same code can be used to format any value that represents a number of bytes. Due to the simplicity of the problem, I decided that this would be a perfect topic for my first article!

Requirements

  • Using B, KB, MB, GB to display the sizes in a logical format.
  • Using commas as thousands separator

An example would be: 1,023 KB (if size = 1023 * 1024 bytes)

Using the code

The code is composed of two functions. The first is InsertSeparators() which is used internally from within the main function to add the thousands separator. The second and main function is FormatSize() which is used to do the all the required formatting.

Following is the code for InsertSeparators(). This function is placed in an unnamed namespace in order to make it a local function.

namespace
{
  /**
   * Converts a positive number to a string while inserting separators.
   *
   * @param dwNumber A positive number to add thousands separator for
   *
   * @return The number with thousand separators as a CString
   */
  CString InsertSeparator (DWORD dwNumber)
  {
    CString str;

    str.Format("%u", dwNumber);

    for (int i = str.GetLength()-3; i > 0; i -= 3)
    {
      str.Insert(i, ",");
    }

    return (str);
  }
}

Following is the code for the FormatSize() function:

/**
 * Converts a filesize to a human readable format.
 *
 * This involves the use of K and M as multipliers.  Hence,
 * strings are formatted as 1024 -> 1KB, 1023 -> 1,023 B,
 * and so on.
 *
 * @param dwFileSize File size to be formatted.
 *
 * @return The formatted filesize as a CString
 */
CString FormatSize (DWORD dwFileSize)
{
  static const DWORD dwKB = 1024;          // Kilobyte
  static const DWORD dwMB = 1024 * dwKB;   // Megabyte
  static const DWORD dwGB = 1024 * dwMB;   // Gigabyte

  DWORD dwNumber, dwRemainder;
  CString strNumber;

  if (dwFileSize < dwKB)
  {
    strNumber = InsertSeparator(dwFileSize) + " B";
  } 
  else
  {
    if (dwFileSize < dwMB)
    {
      dwNumber = dwFileSize / dwKB;
      dwRemainder = (dwFileSize * 100 / dwKB) % 100;

      strNumber.Format("%s.%02d KB", (LPCSTR)InsertSeparator(dwNumber), dwRemainder);
    }
    else
    {
      if (dwFileSize < dwGB)
      {
        dwNumber = dwFileSize / dwMB;
        dwRemainder = (dwFileSize * 100 / dwMB) % 100;
        strNumber.Format("%s.%02d MB", InsertSeparator(dwNumber), dwRemainder);
      }
      else
      {
        if (dwFileSize >= dwGB)
        {
          dwNumber = dwFileSize / dwGB;
          dwRemainder = (dwFileSize * 100 / dwGB) % 100;
          strNumber.Format("%s.%02d GB", InsertSeparator(dwNumber), dwRemainder);
        }
      }
    }
  }

  // Display decimal points only if needed
  // another alternative to this approach is to check before calling str.Format, and 
  // have separate cases depending on whether dwRemainder == 0 or not.
  strNumber.Replace(".00", "");

  return strNumber;
}

Future Improvements

The following are planned future improvements for the next versions of the article:

  • Make the thousands separator and the decimal point dependent on Control Panel settings.
  • Unicode Support

History

01-DEC-2002First version

Edit History

2 Dec 2002 - Initial Edit

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
United States United States
Victor Boctor is a Windows/Linux professional developer. He has worked in the fields of Email Servers, Automatic Test Equipment, Telecommunications, and Embroidery software. He developed software using C#, C++, MFC, Win32, PHP, Cold Fusion, HTML, XHTML, and SQL.

Comments and Discussions

 
GeneralGeneralize Solution Pin
Mina Victor4-Jan-10 14:14
Mina Victor4-Jan-10 14:14 
GeneralEmbroidery Pin
Mohamed Hafez17-Sep-03 6:54
Mohamed Hafez17-Sep-03 6:54 
GeneralAlso see GetNumberFormat() Pin
Ravi Bhavnani1-Dec-02 6:35
professionalRavi Bhavnani1-Dec-02 6:35 
GeneralAnother way Pin
dabs1-Dec-02 2:16
dabs1-Dec-02 2:16 
GeneralRe: Another way Pin
Victor Boctor1-Dec-02 2:31
Victor Boctor1-Dec-02 2:31 
GeneralRe: Another way Pin
Andreas Saurwein4-Dec-02 0:24
Andreas Saurwein4-Dec-02 0:24 
MSDN say:
Note 2: All systems with Internet Explorer 4.0 or 4.01 will have the associated version of Comctl32.dll and Shlwapi.dll (4.71 or 4.72, respectively). However, for systems prior to Windows 98, Internet Explorer 4.0 and 4.01 can be installed with or without the integrated Shell. If they are installed with the integrated Shell, the associated version of Shell32.dll will be installed. If they are installed without the integrated Shell, Shell32.dll is not updated. In other words, the presence of version 4.71 or 4.72 of Comctl32.dll or Shlwapi.dll on a system does not guarantee that Shell32.dll has the same version number. All Windows 98 systems have version 4.72 of Shell32.dll.

So, any system with at least IE4.0 will have that function available.

Victor Boctor wrote:
However, the API does not provide the possibility to control the format, which is possible through altering the above code.

For what? There is a standard way to do it. Not that I want to suppress the value of your code, but someone (MS) has done it already. And it seems to work pretty fine.
And it always produces the same result as seen in Windows Explorer.

There are, by the way, 3 functions to accomplish this: StrFormatByteSize(), StrFormatByteSize64() and StrFormatKBSize().



I don't think this is a serious possesion, and the evil most likely comes from your hand. Colin J Davies, The Lounge

GeneralNice, but... Pin
Anders Molin1-Dec-02 1:02
professionalAnders Molin1-Dec-02 1:02 
GeneralRe: Nice, but... Pin
Victor Boctor1-Dec-02 1:11
Victor Boctor1-Dec-02 1:11 
GeneralRe: Nice, but... Pin
Paolo Messina1-Dec-02 11:55
professionalPaolo Messina1-Dec-02 11:55 
GeneralRe: Nice, but... Pin
Victor Boctor1-Dec-02 15:25
Victor Boctor1-Dec-02 15:25 
GeneralRe: Nice, but... Pin
Anders Dalvander1-Dec-02 21:34
Anders Dalvander1-Dec-02 21:34 
GeneralRe: Nice, but... Pin
Paolo Messina2-Dec-02 6:23
professionalPaolo Messina2-Dec-02 6:23 
GeneralRe: Nice, but... Pin
Victor Boctor2-Dec-02 9:20
Victor Boctor2-Dec-02 9:20 
QuestionToo many numbers? Pin
Anders Dalvander1-Dec-02 1:01
Anders Dalvander1-Dec-02 1:01 
AnswerRe: Too many numbers? Pin
Victor Boctor1-Dec-02 2:18
Victor Boctor1-Dec-02 2:18 
GeneralRe: Too many numbers? Pin
KarstenK2-Dec-02 4:17
mveKarstenK2-Dec-02 4:17 
GeneralRe: Too many numbers? Pin
CompMan442-Sep-08 12:35
CompMan442-Sep-08 12:35 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.