Can ifstream read file more than 2G?

W

Water Lin

I am using ifstream to read file. But when I read a file about 2.8G, the
ifstream will return a size like these:
------------------
-1358985216
------------------

Here is my code:
-----------------------
string dir = "C:\\test";
uint64 size;
ifstream infile(dir.c_str(), ios::in | ios::binary | ios::ate);
if ( infile.is_open() )
{

size = infile.tellg();
}
---------------------

Why the size will be a negative?

Anything wrong?

Someone told me that I should use a 64bit edition of ifstream, is it
true?
 
A

Alf P. Steinbach

* Water Lin:
I am using ifstream to read file. But when I read a file about 2.8G, the
ifstream will return a size like these:
------------------
-1358985216
------------------

Here is my code:
-----------------------
string dir = "C:\\test";
uint64 size;
ifstream infile(dir.c_str(), ios::in | ios::binary | ios::ate);
if ( infile.is_open() )
{

size = infile.tellg();
}

Assuming 'uint64' is an unsigned integer type, it can't be negative.

Anything wrong?

See above.

'tellg' returns a 'pos_type'. By §27.1.2 'pos_type' is by default a 'streampos'
for iostreams. By §21.1.3.1/2 a 'streampos' satisifies the requirements for a
'POS_T' in §21.1.2. That paragraph explains that the requirements are described
in §27.1.2. And then we're full circle, recursive without a base case.

Amazingly, this is noted in §27.2/2, "This synopsis suggests a circularity
between streampos and char_traits<char>."

So at least, while not particularly useful for this issue, and while the
standard goes the extreme lengths to obscure the issue (three layers of
indirection, at the least), the standard is at least truthful.

I'm guessing wildly that someone who doesn't have my strong aversion to
iostreams, I mean, they're just *expletive deleted*, may contribute some tidbit
like e.g. something stated in the C standard, or original intent, or something.

Someone told me that I should use a 64bit edition of ifstream, is it
true?

For files larger than 2^31 bytes that does seem like a good idea, yes.

Or even better, define your own file handling. :)


Cheers & hth.,

- Alf
 
S

Stefan Ram

Water Lin said:
ios::ate(...)tellg()(...)Anything wrong?

»::std::ate« requests a seek to the end of the file.
»seekg« and »tellg« seem to be defined using »pubseekoff« in
ISO/IEC 14882:1998(E), which is defined in terms of »seekoff«,
which is defined based on »::std::fseek«. ISO/IEC 9899:1990
explains about »::std::fseek«:

»A binary stream need not meaningfully support
fseek calls with a whence value of SEEK_END.«

Therefore, one can not assume that one will be able to obtain
the size of a binary file in this way under every
implementation of C++. One needs to look up the documentation
of the implementation to find out whether it supports fseek
calls with a whence value of SEEK_END.

If this is not supported or if the result type of tellg()
is too small, one solution is to read every byte from the
file counting. However, when the result is kept for later
use, one also needs to consider the possibility that the
size of the file might change in the meantime.
 
B

Bo Persson

Water said:
I am using ifstream to read file. But when I read a file about
2.8G, the ifstream will return a size like these:
------------------
-1358985216
------------------

Here is my code:
-----------------------
string dir = "C:\\test";
uint64 size;
ifstream infile(dir.c_str(), ios::in | ios::binary | ios::ate);
if ( infile.is_open() )
{

size = infile.tellg();
}
---------------------

Why the size will be a negative?

Anything wrong?

Someone told me that I should use a 64bit edition of ifstream, is it
true?

It it highly likely that ifstream can read files up to the size
supported by the OS.

On the other hand, tellg is limited by size of long - the largest
integer type in standard C++. What happens when the size or position
is larger than LONG_MAX? I think you just found that out.


Bo Persson
 
J

James Kanze

»::std::ate« requests a seek to the end of the file.
»seekg« and »tellg« seem to be defined using »pubseekoff« in
ISO/IEC 14882:1998(E), which is defined in terms of »seekoff«,
which is defined based on »::std::fseek«. ISO/IEC 9899:1990
explains about »::std::fseek«:
»A binary stream need not meaningfully support
fseek calls with a whence value of SEEK_END.«
Therefore, one can not assume that one will be able to obtain
the size of a binary file in this way under every
implementation of C++. One needs to look up the documentation
of the implementation to find out whether it supports fseek
calls with a whence value of SEEK_END.
If this is not supported or if the result type of tellg()
is too small, one solution is to read every byte from the
file counting. However, when the result is kept for later
use, one also needs to consider the possibility that the
size of the file might change in the meantime.

That's really the only solution anyway. The function tellg
returns a streampos, which isn't even necessarily convertable to
an integral type, and even if it is convertable, the value of
resulting integer doesn't necessarily mean much; it can be some
sort of magic cookie.

In practice, there is no C++ way to determine the size of a
file, because:

1. "size of a file" can mean different things: how much space
the file occupies on the disk or how many bytes you can read
before you encounter end of file are the most obvious
meanings, and

2. many systems don't have an means of determining this
information.

In the end, you have to decide what you really want to know, and
then use some system specific means of obtaining the
information, provided that such a means exists.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top