Failed to read a file

M

Matrixinline

Hi All,

Here is the problem

char* memblock;

std::ifstream file(sFileName, ios::in|ios::binary);
if (file.is_open())
{
size = file.tellg();
memblock = new char [size];
file.seekg (0, ios::beg);
file.read (memblock, size);
file.close();
cout << "the complete file content is in memory";

delete[] memblock;
}



I tried to read a say "JPEG/GIF/EXE/etc.. " files.

I checked in to debugger and find that It reads only
BM╤ from file it means that it does not read till the end of file can
you please let me know why this problem I am facing

One more thing My project is a Unicode one I hope this one will not
affect the File I/O functions

Thanks
Anup
 
D

dolphin

Hi All,

Here is the problem

char* memblock;

std::ifstream file(sFileName, ios::in|ios::binary);
if (file.is_open())
{
size = file.tellg();
memblock = new char [size];
file.seekg (0, ios::beg);
file.read (memblock, size);
file.close();
cout << "the complete file content is in memory";

delete[] memblock;

}

I tried to read a say "JPEG/GIF/EXE/etc.. " files.

I checked in to debugger and find that It reads only
BM¨h from file it means that it does not read till the end of file can
you please let me know why this problem I am facing

One more thing My project is a Unicode one I hope this one will not
affect the File I/O functions

Thanks
Anup

I guess you do not allocat enough momery for memblock .Just guess.
 
J

Jim Langston

Hi All,

Here is the problem

char* memblock;

std::ifstream file(sFileName, ios::in|ios::binary);
if (file.is_open())
{
size = file.tellg();
memblock = new char [size];
file.seekg (0, ios::beg);
file.read (memblock, size);
file.close();
cout << "the complete file content is in memory";

delete[] memblock;
}

I tried to read a say "JPEG/GIF/EXE/etc.. " files.

I checked in to debugger and find that It reads only
BM? from file it means that it does not read till the end of file can
you please let me know why this problem I am facing

One more thing My project is a Unicode one I hope this one will not
affect the File I/O functions

Thanks
Anup

===========

You open the file, get the position. The position at this point is 0. Did
you mean to add the line
file.seekg (0, std::ios::end);
before the size = file.tellg();?

It is hard to say, because this code doesn't compile as written for me.

This, compilable version, runs for me and shows the output of a txt file (I
don't care to look at binary data at this time).

#include <iostream>
#include <string>
#include <fstream>

int main()
{
char* memblock;

std::string sFileName="console5.cpp";
std::ifstream file(sFileName.c_str(), std::ios::in|std::ios::binary);
if (file.is_open())
{
file.seekg (0, std::ios::end);
unsigned int size = file.tellg();
std::cout << "Size:" << size << "\n";
memblock = new char [size];
file.seekg (0, std::ios::beg);
file.read (memblock, size);
file.close();
std::cout << "the complete file content is in memory\n";
for ( int i = 0; i < size; ++i )
std::cout << memblock;

delete[] memblock;
}

}
 
J

James Kanze

"Matrixinline" <[email protected]> wrote in message

[...]
You open the file, get the position. The position at this
point is 0. Did you mean to add the line
file.seekg (0, std::ios::end);
before the size = file.tellg();?

This may work on a lot of systems, but formally, there's no
guarantee that the results of tellg() can be implicitly
converted to an integral type, and there's even less of a
guarantee that they represent the number of bytes in the file
between the current position and the beginning of the file; a
system can use any sort of magic encoding it wants. (In
practice, of course, it probably works under Unix, and for files
opened in binary under Windows. Provided the files aren't too
big.)

The simplest and surest way of reading all of a file into memory
is:

std::vector< char > v(
(std::istreambuf_iterator< char >( file )),
(std::istreambuf_iterator< char >()) ) ;

If you're unsure of the file size, you might want to wrap it in
a try block, catching bad_alloc.
 
K

Keith Willis

The simplest and surest way of reading all of a file into memory
is:

std::vector< char > v(
(std::istreambuf_iterator< char >( file )),
(std::istreambuf_iterator< char >()) ) ;

If you're unsure of the file size, you might want to wrap it in
a try block, catching bad_alloc.

James, could you elaborate on this mechanism for me? I've been using
the

file.seekg(0,ios::end);
file.tellg();

method for ages. How does your contruction work, and will a simple
v.size() give me the data size afterwards?
 
J

James Kanze

James, could you elaborate on this mechanism for me?

It's just a more or less classical use of streambuf_iterator;
you can construct a vector with an iterator pair of any type.
All it does is read the entire file into the vector, in the
constructor.
I've been using the

method for ages.

It seems to be a common idiom, however: file.tellg() returns a
streampos, which must be a class type (it is required to contain
multi-byte state, as well as the physical position in the file).
The standard requires an implicit conversion of this to
streamoff, but because streampos is a user defined type, this
must be a user defined conversion. The standard also requires
that streamoff be convertible into an integral type. However:
if streamoff is also a class type, the conversion of a streampos
to an integral type involves two user defined conversions, and
can't occur implicitly. Typically, streamoff is a typedef to
an integral type, so you're OK. But there are still two
potential problems: the mapping of the integral value of
streamoff may not be linear (not likely on a system modeling
files as byte streams, like Unix or Windows, but on more complex
systems, who knows), and the actual file size might not fit in
the target integral type. (On all of the systems I use, int is
32 bits, but files can be---and often are-- considerably bigger
than what will fit into 32 bits.)
How does your contruction work, and will a simple v.size()
give me the data size afterwards?

It works because it constructs a vector with the contents of the
file, by reading it. And v.size() will give you the exact value
of the number of bytes read.
 
K

Keith Willis

It's just a more or less classical use of streambuf_iterator;
you can construct a vector with an iterator pair of any type.
All it does is read the entire file into the vector, in the
constructor.

OK, I'm trying this and am having some problems; what am I doing
wrong?! Given this simple example:

//-------------------------------------------
#include <iostream>
#include <vector>
#include <fstream>

using namespace std;

int main(int argc, char** argv)
{
if (argc > 1)
{
ifstream file(argv[1], ios::binary);
vector<unsigned char> v(istreambuf_iterator<unsigned char>(file),
istreambuf_iterator<unsigned char>());

cout << "Read " << v.size() << " bytes from '"
<< argv[1] << "'\n";
}
return(0);
}
//-------------------------------------------

I get the following at compile time:

xx.cc: In function `int main(int, char**)':
xx.cc:16: error: request for member `size' in `v', which is of
non-class type `std::vector<unsigned char, std::allocator<unsigned
char> > ()(std::istreambuf_iterator<unsigned char,
std::char_traits<unsigned char> >, std::istreambuf_iterator<unsigned
char, std::char_traits<unsigned char> > (*)())'
 
K

Keith Willis

OK, I'm trying this and am having some problems; what am I doing
wrong?! Given this simple example:

I know, I know - following up one's own posts is frowned upon. But I
just worked out how to use this idiom, so I thought I'd save anyone
else the time of explaining it. This version works:

#include <iostream>
#include <vector>
#include <fstream>

using namespace std;

int main(int argc, char** argv)
{
if (argc > 1)
{
ifstream file(argv[1], ios::binary);

istreambuf_iterator<unsigned char> start(file.rdbuf());
istreambuf_iterator<unsigned char> end;

vector<char> v(start,end);

cout << "Read " << v.size() << " bytes from '"
<< argv[1] << "'\n";
}
return(0);
}
 
K

Keith Willis

It's just a more or less classical use of streambuf_iterator;
you can construct a vector with an iterator pair of any type.
All it does is read the entire file into the vector, in the
constructor.
Typically, streamoff is a typedef to
an integral type, so you're OK. But there are still two
potential problems: the mapping of the integral value of
streamoff may not be linear (not likely on a system modeling
files as byte streams, like Unix or Windows, but on more complex
systems, who knows), and the actual file size might not fit in
the target integral type. (On all of the systems I use, int is
32 bits, but files can be---and often are-- considerably bigger
than what will fit into 32 bits.)

OK, I've been playing with this and have a question. Your reservation
about using the seekg() and tellg() calls was partly because the size
of the file might not be representable by an integral type. But, if I
use this istreambuf_iterator method to read the data into my vector
vec, I then check the size of the data read using vec.size(), yes? But
vector::size() seems to return a size_type value, and that is an
unsigned integer type, at least according to
http://www.cplusplus.com/reference/stl/vector/size.html, so I still
can't read files with a size larger than will fit in 32 bits...

Or am I missing something here?
 
J

James Kanze

OK, I've been playing with this and have a question. Your
reservation about using the seekg() and tellg() calls was
partly because the size of the file might not be representable
by an integral type.

Partially. Formally, there is no requirement of convertibility,
and no requirement that the integral values resulting from the
conversion will be meaningful in any traditional sense of the
word. Practically, at least under Windows and (probably most)
Unix, however, the only real problem will be the fact that the
size of the file typically isn't representable as an int.
(If you use long long, perhaps, you won't have a problem.)
But, if I
use this istreambuf_iterator method to read the data into my vector
vec, I then check the size of the data read using vec.size(), yes? But
vector::size() seems to return a size_type value, and that is an
unsigned integer type, at least according tohttp://www.cplusplus.com/reference/stl/vector/size.html, so I still
can't read files with a size larger than will fit in 32 bits...
Or am I missing something here?

Not really. The main difference is that if you overflow reading
into an std::vector, you get an exception (bad_alloc); if you
overflow converting to an int, you get some implementation
defined value which has little relationship to the actual size.
 

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,769
Messages
2,569,582
Members
45,058
Latest member
QQXCharlot

Latest Threads

Top