468,510 Members | 1,753 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 468,510 developers. It's quick & easy.

Handling file sizes correctly

Hello,

in my application, I want to print file sizes in a human readable
format. However, I remember a thread here which dealt with a similar
issue, and people said it'd be a bad idea to write numbers like 1024 and
so on explicitly. Unfortunately I can't remember the reason.

Can you elaborate on that?

Thanks.

--
Matthias Kaeppler
Jul 23 '05 #1
5 3073
"Matthias Kaeppler" <no****@digitalraid.com> wrote in message
news:d3c265$6tr$05
in my application, I want to print file sizes in a human readable
format. However, I remember a thread here which dealt with a similar
issue, and people said it'd be a bad idea to write numbers like 1024 and
so on explicitly. Unfortunately I can't remember the reason.

Can you elaborate on that?


Hmmm. To write numbers in human readable format seems to be always safe. I
think by writing directly they might have meant writing the bit
representation to the file. Problem with this method is that it is not
portable, as different platforms has different sizeof for the same integer
type, and the endian-ness may be different too, plus there will be other
differences in floating point representation.
Jul 23 '05 #2
Matthias Kaeppler wrote:
Hello,

in my application, I want to print file sizes in a human readable
format. However, I remember a thread here which dealt with a similar
issue, and people said it'd be a bad idea to write numbers like 1024 and
so on explicitly. Unfortunately I can't remember the reason.

Can you elaborate on that?

Thanks.


Maybe it's a better idea after all if I post my code, and you tell me
whether it's okay or not. The function is supposed to create a string
from an integer holding the formatted size:

Glib::ustring FileBrowser::get_file_size( const boostfs::path& path )
{
Glib::ustring str_size;

try
{
if( boostfs::is_directory(path) )
return "0";

boost::intmax_t size = boostfs::file_size( path );

const int KILO_BYTE = 1024;
const int MEGA_BYTE = KILO_BYTE * 1024;
const int GIGA_BYTE = MEGA_BYTE * 1024;

if( size >= GIGA_BYTE )
{
size /= GIGA_BYTE;
str_size = boost::lexical_cast<Glib::ustring>(size) + " GB";
}
else if( size >= MEGA_BYTE )
{
size /= MEGA_BYTE;
str_size = boost::lexical_cast<Glib::ustring>(size) + " MB";
}
else if( size >= KILO_BYTE )
{
size /= KILO_BYTE;
str_size = boost::lexical_cast<Glib::ustring>(size) + " KB";
}
else
{
str_size = boost::lexical_cast<Glib::ustring>(size) + " B";
}
}
catch( const boostfs::filesystem_error& e )
{
std::cerr << e.what() << std::endl;
}

return str_size;
}

By the way, it would be cool if the file size wasn't reduced to a
rounded integer, but a float or double has too many digits.
Any idea how I can trim them to only one digit behind the dot, e.g.:

12.3 MB instead of 12.3xxxxxxx MB or such.

--
Matthias Kaeppler
Jul 23 '05 #3

"Matthias Kaeppler" <no****@digitalraid.com> wrote in message
news:d3*************@news.t-online.com...
Matthias Kaeppler wrote:
Hello,

in my application, I want to print file sizes in a human readable format.
However, I remember a thread here which dealt with a similar issue, and
people said it'd be a bad idea to write numbers like 1024 and so on
explicitly. Unfortunately I can't remember the reason.

Can you elaborate on that?

Thanks.


Maybe it's a better idea after all if I post my code, and you tell me
whether it's okay or not. The function is supposed to create a string from
an integer holding the formatted size:

Glib::ustring FileBrowser::get_file_size( const boostfs::path& path )
{
Glib::ustring str_size;

try
{
if( boostfs::is_directory(path) )
return "0";

boost::intmax_t size = boostfs::file_size( path );

const int KILO_BYTE = 1024;
const int MEGA_BYTE = KILO_BYTE * 1024;
const int GIGA_BYTE = MEGA_BYTE * 1024;

if( size >= GIGA_BYTE )
{
size /= GIGA_BYTE;
str_size = boost::lexical_cast<Glib::ustring>(size) + " GB";
}
else if( size >= MEGA_BYTE )
{
size /= MEGA_BYTE;
str_size = boost::lexical_cast<Glib::ustring>(size) + " MB";
}
else if( size >= KILO_BYTE )
{
size /= KILO_BYTE;
str_size = boost::lexical_cast<Glib::ustring>(size) + " KB";
}
else
{
str_size = boost::lexical_cast<Glib::ustring>(size) + " B";
}
}
catch( const boostfs::filesystem_error& e )
{
std::cerr << e.what() << std::endl;
}

return str_size;
}

By the way, it would be cool if the file size wasn't reduced to a rounded
integer, but a float or double has too many digits.
Any idea how I can trim them to only one digit behind the dot, e.g.:

12.3 MB instead of 12.3xxxxxxx MB or such.

--
Matthias Kaeppler


Matthias, I made the following function to print filesize formated like 625
b, 1.34 Kb, 12.8 Kb, 16.3 Mb, 4.23 Gb, etc. to fit in a table. Just send
the filesize as a function argument and the function couts the text. I'd be
easy enough to modify the function to return a string.

Sorry if my long lines don't print very well...

void printFileSize(unsigned long int lof_in){
cout.precision(3);
cout << setw(4) << setfill(' ');
(lof_in < (1 << 10))
? (cout << lof_in << " b\t")
: (lof_in < (1 << 20))
? (cout << (static_cast<float>(lof_in)/(1 << 10)) << " Kb\t")
: (lof_in < (1 << 30))
? (cout << (static_cast<float>(lof_in)/(1 << 20)) << "
Mb\t" )
: (cout << (static_cast<float>(lof_in)/(1 << 30)) << "
Gb\t");
}
Jul 23 '05 #4
Joe C wrote:
"Matthias Kaeppler" <no****@digitalraid.com> wrote in message
news:d3*************@news.t-online.com...
Matthias Kaeppler wrote:
Hello,

in my application, I want to print file sizes in a human readable format.
However, I remember a thread here which dealt with a similar issue, and
people said it'd be a bad idea to write numbers like 1024 and so on
explicitly. Unfortunately I can't remember the reason.

Can you elaborate on that?

Thanks.


Maybe it's a better idea after all if I post my code, and you tell me
whether it's okay or not. The function is supposed to create a string from
an integer holding the formatted size:

Glib::ustring FileBrowser::get_file_size( const boostfs::path& path )
{
Glib::ustring str_size;

try
{
if( boostfs::is_directory(path) )
return "0";

boost::intmax_t size = boostfs::file_size( path );

const int KILO_BYTE = 1024;
const int MEGA_BYTE = KILO_BYTE * 1024;
const int GIGA_BYTE = MEGA_BYTE * 1024;

if( size >= GIGA_BYTE )
{
size /= GIGA_BYTE;
str_size = boost::lexical_cast<Glib::ustring>(size) + " GB";
}
else if( size >= MEGA_BYTE )
{
size /= MEGA_BYTE;
str_size = boost::lexical_cast<Glib::ustring>(size) + " MB";
}
else if( size >= KILO_BYTE )
{
size /= KILO_BYTE;
str_size = boost::lexical_cast<Glib::ustring>(size) + " KB";
}
else
{
str_size = boost::lexical_cast<Glib::ustring>(size) + " B";
}
}
catch( const boostfs::filesystem_error& e )
{
std::cerr << e.what() << std::endl;
}

return str_size;
}

By the way, it would be cool if the file size wasn't reduced to a rounded
integer, but a float or double has too many digits.
Any idea how I can trim them to only one digit behind the dot, e.g.:

12.3 MB instead of 12.3xxxxxxx MB or such.

--
Matthias Kaeppler

Matthias, I made the following function to print filesize formated like 625
b, 1.34 Kb, 12.8 Kb, 16.3 Mb, 4.23 Gb, etc. to fit in a table. Just send
the filesize as a function argument and the function couts the text. I'd be
easy enough to modify the function to return a string.

Sorry if my long lines don't print very well...

void printFileSize(unsigned long int lof_in){
cout.precision(3);
cout << setw(4) << setfill(' ');
(lof_in < (1 << 10))
? (cout << lof_in << " b\t")
: (lof_in < (1 << 20))
? (cout << (static_cast<float>(lof_in)/(1 << 10)) << " Kb\t")
: (lof_in < (1 << 30))
? (cout << (static_cast<float>(lof_in)/(1 << 20)) << "
Mb\t" )
: (cout << (static_cast<float>(lof_in)/(1 << 30)) << "
Gb\t");
}


Ah, of course, the std::cout::precision thing is the key. Thanks a lot
for that function Joe!

--
Matthias Kaeppler
Jul 23 '05 #5
Joe C wrote:
"Matthias Kaeppler" <no****@digitalraid.com> wrote in message
news:d3*************@news.t-online.com...
Matthias Kaeppler wrote:
Hello,

in my application, I want to print file sizes in a human readable format.
However, I remember a thread here which dealt with a similar issue, and
people said it'd be a bad idea to write numbers like 1024 and so on
explicitly. Unfortunately I can't remember the reason.

Can you elaborate on that?

Thanks.


Maybe it's a better idea after all if I post my code, and you tell me
whether it's okay or not. The function is supposed to create a string from
an integer holding the formatted size:

Glib::ustring FileBrowser::get_file_size( const boostfs::path& path )
{
Glib::ustring str_size;

try
{
if( boostfs::is_directory(path) )
return "0";

boost::intmax_t size = boostfs::file_size( path );

const int KILO_BYTE = 1024;
const int MEGA_BYTE = KILO_BYTE * 1024;
const int GIGA_BYTE = MEGA_BYTE * 1024;

if( size >= GIGA_BYTE )
{
size /= GIGA_BYTE;
str_size = boost::lexical_cast<Glib::ustring>(size) + " GB";
}
else if( size >= MEGA_BYTE )
{
size /= MEGA_BYTE;
str_size = boost::lexical_cast<Glib::ustring>(size) + " MB";
}
else if( size >= KILO_BYTE )
{
size /= KILO_BYTE;
str_size = boost::lexical_cast<Glib::ustring>(size) + " KB";
}
else
{
str_size = boost::lexical_cast<Glib::ustring>(size) + " B";
}
}
catch( const boostfs::filesystem_error& e )
{
std::cerr << e.what() << std::endl;
}

return str_size;
}

By the way, it would be cool if the file size wasn't reduced to a rounded
integer, but a float or double has too many digits.
Any idea how I can trim them to only one digit behind the dot, e.g.:

12.3 MB instead of 12.3xxxxxxx MB or such.

--
Matthias Kaeppler

Matthias, I made the following function to print filesize formated like 625
b, 1.34 Kb, 12.8 Kb, 16.3 Mb, 4.23 Gb, etc. to fit in a table. Just send
the filesize as a function argument and the function couts the text. I'd be
easy enough to modify the function to return a string.

Sorry if my long lines don't print very well...

void printFileSize(unsigned long int lof_in){
cout.precision(3);
cout << setw(4) << setfill(' ');
(lof_in < (1 << 10))
? (cout << lof_in << " b\t")
: (lof_in < (1 << 20))
? (cout << (static_cast<float>(lof_in)/(1 << 10)) << " Kb\t")
: (lof_in < (1 << 30))
? (cout << (static_cast<float>(lof_in)/(1 << 20)) << "
Mb\t" )
: (cout << (static_cast<float>(lof_in)/(1 << 30)) << "
Gb\t");
}


Hmmm, based on your code, I have changed mine to look like this:

Glib::ustring FileBrowser::get_file_size( const boostfs::path& path )
{
std::ostringstream sstream;
sstream.precision( 2 );

try
{
if( boostfs::is_directory(path) )
return "0";

boost::intmax_t size = boostfs::file_size( path );

if( size >= GIGA_BYTE )
{
sstream << (static_cast<float>(size) / GIGA_BYTE);
sstream << " GB";
}
else if( size >= MEGA_BYTE )
{
sstream << (static_cast<float>(size) / MEGA_BYTE);
sstream << " MB";
}
else if( size >= KILO_BYTE )
{
sstream << (static_cast<float>(size) / KILO_BYTE);
sstream << " KB";
}
else
{
sstream << size;
sstream << " B";
}
}
catch( const boostfs::filesystem_error& e )
{
std::cerr << e.what() << std::endl;
}

return sstream.str();
}

However, it sometimes prints garbage, like "1.7e+02 KB" for a file which
is only a couple of KB large and I don't find my error.

--
Matthias Kaeppler
Jul 23 '05 #6

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

115 posts views Thread by J | last post: by
4 posts views Thread by Vagabond Software | last post: by
34 posts views Thread by rawCoder | last post: by
3 posts views Thread by Binu C | last post: by
3 posts views Thread by kayahr | last post: by
10 posts views Thread by deciacco | last post: by
reply views Thread by NPC403 | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.