Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reading binary data into std::string c++

Tags:

c++

string

binary

I am trying to read data from binary file to an std::string.Here is what I have tried at first.

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

using namespace std;

int main(int argc, char const *argv[])
{
    fstream file("output.bin" , ios::out | ios::binary | ios::in);
    string my_str(5, '\0');
    file.read(my_str.c_str(), 5);
    cout << "String = " << my_str<< endl ;
}

And the compiler gave the error :

error: invalid conversion from ‘const char*’ to ‘std::basic_istream<char>::char_type* {aka char*}’ [-fpermissive]
  file.read(my_str.c_str(), 5);

As far as I understand, c_str() returns a const pointer which cannot be used in read method, so I changed my approach a little bit(which you can see below). Is there a better way to do this ?

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

using namespace std;

int main(int argc, char const *argv[])
{
    fstream file("output.bin" , ios::out | ios::binary | ios::in);
    string my_str(5, '\0');
    char buffer[6];
    file.read(buffer, 5);
    buffer[5] = '\0';
    my_str = string(buffer);

    cout << "String = " << my_str<< endl ;
}

ps : forgive me if I could not make myself clear, this is my first time here :)

like image 782
baris_esmer Avatar asked Jul 27 '16 20:07

baris_esmer


People also ask

How to read binary file in C++?

C++ read binary file is a file Input/Output operation that is handled by the stream-based interface of the C++ Standard Template Library. You’ll need to utilize the std::fstream class for creating a file stream object first, and then the contents of it can be read using different methods based on the needs of the solution.

How to read binary stream from a file using fopen?

After the fopen returns the file pointer, we can call the fread function to read binary stream. fread takes four arguments, the first of which is the void pointer to the location where the read bytes should be stored. The next two arguments specify the size and number of the data items that need to be read from the given file.

Is it possible to open stdin in binary?

This is not the answer. stdin is a buffered input stream, and fread () will read buffered data, and on Windows it will be reading in text mode and convert to a single character, which will be bad for binary data. I don't know what OS you are running, but you typically cannot "open stdin in binary".

How to convert a binary file to text?

You can also convert binary to text: "convert to hex text string" and "uuencode base 64" are two common ways to do this. You'll want to read the bytes as numbers (of type long long probably). Then you can print those using formatting specifiers like this:


3 Answers

In C++11, the way to get a non-const pointer to the string's data is:

file.read(&my_str[0], 5);

C++17 will introduce non-const data() for this as well:

file.read(my_str.data(), 5);
like image 193
Barry Avatar answered Oct 18 '22 03:10

Barry


another way, using standard algorithms:

#include <iostream>
#include <string>
#include <fstream>
#include <algorithm>
#include <iterator>

using namespace std;

int main(int argc, char const *argv[])
{
    fstream file("output.bin" , ios::out | ios::binary | ios::in);

    auto my_str = string();

    copy_n(istream_iterator<char>(file), 
           5, 
           std::back_inserter(my_str));

    cout << "String = " << my_str<< endl ;
}
like image 20
Richard Hodges Avatar answered Oct 18 '22 03:10

Richard Hodges


std::string is specially designed to work with strings and with c-style strings as well, so this fact will work against you in this situation. For example your code:

char buffer[6];
file.read(buffer, 5);
buffer[5] = '\0';
my_str = string(buffer);

what is wrong with it? You are reading binary data and who guarantees that there won't be '\0' byte there? You can fix it by:

my_str = string(buffer,5);

but this shows the point - std::string as a buffer is not a good choice. So you better use std::vector<char> or even better std::vector<uint8_t> which has method data() but will not implicitly convert from c-string, output to std::ostream etc.

like image 31
Slava Avatar answered Oct 18 '22 03:10

Slava