哪种方法是将二进制文件内容读入std :: string的最佳方式?

4

可能是重复问题:
如何使用 istream 处理字符串

该问题可能已经有了重复的解决方案,请参考上面提供的链接。
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();

这是我知道的方法:
1. 可能不安全。
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());
}

1
你可能会发现这个回答对另一个问题有用:https://dev59.com/jW035IYBdhLWcg3wGL5T#5632723 - R. Martinho Fernandes
我认为第一个比第二个好得多。 - Marius Bancila
3
你最好使用while (ifile)而不是while (!ifile.eof())(后者可能会变成无限循环)。 - Christian Ammer
2
请查看以下问题,了解正确读取二进制文件的方法:https://dev59.com/rW445IYBdhLWcg3wpL1_ - CharlesB
2
@Mihran:使用!stream.eof()循环是错误的。 (http://www.parashift.com/c++-faq-lite/input-output.html#faq-15.5) - Lightness Races in Orbit
显示剩余8条评论
2个回答

4
如果文件是二进制的,它可能包含'\0'这个奇怪的字符,这个字符在std::string中被包含是有问题的。虽然我认为你可以这样做,但你会遇到问题,因为一些对std::string的操作需要一个以null结尾的const char*。相反,使用std::vector<char>是更安全的方式。
如果你仍然想使用字符串,只需调用一个循环来调用std::string::append(size_t, char)即可。
while(!ifile.eof()) {
   contents.append(1, ifile.get());
}

编辑:我认为你还可以在以下方面做一些工作:

std::string contents(std::istreambuf_iterator<char>(ifile), std::istreambuf_iterator<char>());

先从简单的方案开始,如果你有真实数据证明它很慢再进行优化。过早的优化是万恶之源 -- DonaldKnuth - Giovanni Funchal
4
е“Әдәӣstd::stringж“ҚдҪңеҸҜд»ҘжҺҘеҸ—const char*пјҹдёҖдәӣйҮҚиҪҪе…Ғи®ёд»Һcharж•°з»„дёӯ_иҫ“е…Ҙ_пјҢдҪҶжҳҜ_std::stringеҜ№NULLеҖје…·жңүе®үе…ЁжҖ§_гҖӮ - Lightness Races in Orbit
1
构造函数 std::string(const char* s)operator+=(const char* s) 等都以 const char* 作为参数,这意味着如果参数为 NULL,则会被解释为字符串结束,从而截取了你实际想要的部分。 - Giovanni Funchal
1
当然可以,但它们只是为了方便而提供的,对于相同的输入,存在std::string重载(并且更受欢迎)。std::string中没有固有的NULL结尾。这里的类比是,如果您将C字符串复制到std::vector<char>中,仍然必须使用strlen。还要注意,您可以为这些函数中的第一个提供显式大小。 - Lightness Races in Orbit

-1
你应该清楚二进制文件和字符串的概念。你是想读取文件内容,还是想将文件的二进制表示转换成字符串?通常使用 unsigned char[] 缓冲区来存储二进制文件的内容,而使用 string 来存储文本文件的内容。

1
为什么不呢?它是无符号字符,在Windows中它是BYTE。请关注于这个想法,而非这种细节! - longbkit
为什么不呢?这取决于你的目的。通常我们读取二进制文件是为了关注每个字节(或类似的)以处理数据。因此,使用原始数组可以更轻松、更快速地处理数据。如果您事先知道文件大小绝不会大于一定数量的字节,那么只需使用固定数组;否则,请使用动态数组(有许多方法可以做到这一点,如果不必要,我就不详细说明)。 - longbkit
1
дёҖдёӘеҺҹе§Ӣзҡ„char[]жҲ–иҖ…еҠЁжҖҒеҲҶй…Қзҡ„ж•°з»„(char*)жҳҜеҗҰжҜ”vector<char>жӣҙеҝ«(еҰӮжһңжңүжӣҙеҝ«зҡ„иҜқ)? еӣ дёәvector<char>жңүжҳҺжҳҫзҡ„дјҳеҠҝпјҢжңҖйҮҚиҰҒзҡ„жҳҜе®ғдёҚдјҡеҝҳи®°иҮӘе·ұзҡ„еӨ§е°ҸпјҢ并且дёҚйңҖиҰҒжүӢеҠЁеҶ…еӯҳз®ЎзҗҶгҖӮ - R. Martinho Fernandes
好的,我同意。char[] 只会快一点点,但是感谢您。 - longbkit
@Martinho:char* 并不是一个动态分配的数组(虽然它可能指向一个)。而且,数组并不一定比向量快 - Lightness Races in Orbit
显示剩余2条评论

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