4

Possible Duplicate:
How to use istream with strings

std::ifstream ifile(absolute_file_path.c_str(),std::ios::binary | std::ios::in | std::ios::ate);
if (ifile.is_open()==false) 
{
    throw std::runtime_error("Unable open the file.");
}
std::stirng file_content;
//here I need good way to read full file to file_content
//note: the file is binary
ifile.close();

This are ways I know:

1.Maybe not safe

file_content.resize(ifile.tellg());
ifile.seekg(0,std::ios::beg);
if(!ifile.read(const_cast<char *>(file_content.data()), file_content.size()));
{
    throw std::runtime_errro("failed to read file:");
}
ifile.close();

2.Slow

file_content.reserve(ifile.tellg());
ifile.seekg(0,std::ios::beg);
while(ifile)
{
    file_content += (char)(ifile.get());
}
Community
  • 1
  • 1
Mihran Hovsepyan
  • 10,110
  • 13
  • 57
  • 108
  • 1
    You may find this answer to another question useful: http://stackoverflow.com/questions/5632572/what-to-watch-out-for-when-converting-a-stdstring-to-a-char-for-c-function/5632723#5632723 – R. Martinho Fernandes Jun 30 '11 at 08:49
  • a string is not designed to hold binary data, you should use something like a vector – CharlesB Jun 30 '11 at 08:49
  • I'd say the first is much better than the second – Marius Bancila Jun 30 '11 at 08:50
  • @CharlesB then why it has member function data()? – Mihran Hovsepyan Jun 30 '11 at 08:55
  • @Mihran it doesn't mean that it can be used to hold binary data. Also as you pointed it, it unsafe to use it for write access, see [cplusplus ref](http://www.cplusplus.com/reference/string/string/data/). – CharlesB Jun 30 '11 at 09:00
  • 2
    You should better use `while (ifile)` instead of `while (!ifile.eof())` (this could turn into a endless loop). – Christian Ammer Jun 30 '11 at 09:03
  • @CharlesB: Strings can hold binary data just fine. cplusplus.com is a poor reference. Nobody is suggesting writing through a `const char*`. – Lightness Races in Orbit Jun 30 '11 at 09:03
  • 2
    see this question for the right way to read a binary file: http://stackoverflow.com/q/4761529/11343 – CharlesB Jun 30 '11 at 09:03
  • Or, better yet, activate an exception on fail. – Giovanni Funchal Jun 30 '11 at 09:04
  • 2
    @Mihran: [Looping with `!stream.eof()` is wrong.](http://www.parashift.com/c++-faq-lite/input-output.html#faq-15.5) – Lightness Races in Orbit Jun 30 '11 at 09:04
  • @Tomalak I'm not saying you can't use strings to hold binary, just that it's not made for it. And yes, Mihran is using const_casted data() to write content, which is far from being elegant, although it works – CharlesB Jun 30 '11 at 09:09
  • 2 more links on the subject: [C++ STL's String eqivalent for Binary Data](http://stackoverflow.com/q/837521/11343) and [“Proper” way to store binary data with C++/STL](http://stackoverflow.com/q/441203/11343) – CharlesB Jun 30 '11 at 09:09
  • @CharlesB: I would also pick `vector`, personally. But you did say "a string is not designed to hold binary data", which is misleading because there is no reason that it cannot. – Lightness Races in Orbit Jun 30 '11 at 09:11

2 Answers2

4

If the file is binary, it might contain '\0' which is a weird character to be contained in an std::string. Although I think you could do that, you will be asking for problems because some operations on a std::string take a const char* which is null-terminated. Instead, go with std::vector<char>, a much safer way.

If you go with strings anyway, just do a loop calling std::string::append(size_t, char).

while(!ifile.eof()) {
   contents.append(1, ifile.get());
}

EDIT: I think you can also do something in the lines of:

std::string contents(std::istreambuf_iterator<char>(ifile), std::istreambuf_iterator<char>());
Giovanni Funchal
  • 8,295
  • 12
  • 54
  • 103
  • Start with simple solution, optimize later if you have real life data showing it is slow. Premature optimization is the root of all evil -- DonaldKnuth – Giovanni Funchal Jun 30 '11 at 08:55
  • 4
    Which `std::string` operations take `const char*`? Some overloads allow _input_ from a `char` array, but _`std::string` is NULL-safe`_ – Lightness Races in Orbit Jun 30 '11 at 09:05
  • 1
    The constructor `std::string(const char* s)`, the `operator+=(const char* s)` etc all take a `const char*` as parameter, this means that if the argument has a NULL then it will be interpreted as end of string slicing part of what you actually wanted. – Giovanni Funchal Jul 02 '11 at 10:57
  • 1
    Sure, but they are only provided for convenience, and `std::string` overloads exist (and are preferred) for the same inputs. There's nothing inherent in an `std::string` that's NULL-terminated. The analogy here is that you _still have to use, say, `strlen`_ if you copied a C-string into a `std::vector`. Also note that you can provide an explicit size to the first of those functions. – Lightness Races in Orbit Jul 02 '11 at 12:33
-1

You should be clear with binary file and string. Do you mean to read the content of that file, or you want to read binary representation of the file to string? Normally an unsigned char[] buffer is used to store content of binary files. And string is used to store content of a text file.

R. Martinho Fernandes
  • 209,766
  • 68
  • 412
  • 492
longbkit
  • 878
  • 1
  • 8
  • 19
  • 1
    why not? it's unsigned char, and in Windows it's BYTE. Please focus on the idea, not this kind of detail! – longbkit Jun 30 '11 at 08:57
  • OK, I should be more careful next time :-) – longbkit Jun 30 '11 at 09:01
  • Noooooo do not recommend raw arrays. There is absolutely no reason for that. – Lightness Races in Orbit Jun 30 '11 at 09:06
  • Why not? It depends on your purpose. Usually we read binary file to care about every single byte (or so) to process data. So using raw arrays may help process data easier and faster. If you know in advance the filesize is no way larger than a number of bytes, simply use a fixed array, or if not, use dynamic array instead (there are many ways to do this, I would not say in detail if needless) – longbkit Jun 30 '11 at 09:16
  • 1
    Is a raw `char[]` or a dynamically allocated array (`char*`) significantly faster (if at all faster) than a `vector`? Because a `vector` has obvious advantages, the most important being the facts that it doesn't forget its own size, and that it doesn't require manual memory management. – R. Martinho Fernandes Jun 30 '11 at 09:26
  • Ok I agree. char[] only faster in a very tiny amount of time. Thank you. – longbkit Jun 30 '11 at 10:25
  • @Martinho: `char*` is not a dynamically allocated array (though it may point to one). And, no, [arrays do not have to be faster than vectors](http://www.xs4all.nl/~weegen/eelis/vector-speed.cpp). – Lightness Races in Orbit Jul 02 '11 at 12:35