将二进制数据读入到C++的std::string中

5

我正在尝试从二进制文件中读取数据并存储到std::string中。以下是我最初尝试的代码。

#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 ;
}

编译器报错:

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

据我所知,c_str()返回一个不能用于读取方法的常量指针,因此我稍微改变了我的方法(如下所示)。有更好的方法吗?
#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 ;
}

提示:如果我表达不清楚,请原谅,这是我第一次在这里 :)


我会使用 std::vector<char>std::vector<uint8_t> 代替 std::string - Slava
我从来不明白为什么人们会使用 std::string 来处理二进制数据。请记住,这个容器的 value_typechar,这可能会导致与符号扩展相关的问题(例如,想想 my_str[3] == 0x95 的结果会是什么)。你可能想要使用 std::vector<std::uint8_t> - Daniel Kamil Kozar
3个回答

8

在C++11中,获得字符串数据的非const指针的方法如下:

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

C++17还将引入非const data()

file.read(my_str.data(), 5);

4
这些奇怪的特点使得C++变得非常出色。35年晚了,才添加了一个方便的非const方法来获取内部字符串缓冲区。 - Hatted Rooster
为了确保,在调用read方法之前,my_str的大小应该大于或等于5,对吗?@Barry - baris_esmer
@baris_esmer 当然可以。所有常见的警示都适用。 - Barry

2

另一种方法是使用标准算法:

#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 ;
}

2

std::string 是专门为字符串和 c 风格的字符串设计的,因此在这种情况下,这一事实会对你产生不利影响。例如,你的代码:

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

它有什么问题?你正在读取二进制数据,谁能保证那里不会有'\0'字节呢?你可以通过以下方式解决:

my_str = string(buffer,5);

但这表明一个重要的观点 - 用std::string作为缓冲区不是一个好选择。因此,最好使用std::vector<char>,甚至更好的是std::vector<uint8_t>,它具有方法data(),但不会从c-string隐式转换,输出到std::ostream等。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接