我需要将整个文件读入内存并将其放在C++中std::string.
如果我把它读成a char[],答案很简单:
std::ifstream t;
int length;
t.open("file.txt"); // open input file
t.seekg(0, std::ios::end); // go to the end
length = t.tellg(); // report location (this is the length)
t.seekg(0, std::ios::beg); // go back to the beginning
buffer = new char[length]; // allocate memory for a buffer of appropriate dimension
t.read(buffer, length); // read the whole file into the buffer
t.close(); // close file handle
// ... Do stuff with buffer here ...
Run Code Online (Sandbox Code Playgroud)
现在,我想做同样的事情,但是使用a std::string而不是a char[] …
如何将文件读入a std::string,即一次读取整个文件?
文本或二进制模式应由调用者指定.该解决方案应符合标准,便携且高效.它不应该不必要地复制字符串的数据,它应该避免在读取字符串时重新分配内存.
实现此目的的一种方法是统计文件大小,调整大小std::string和fread()进入std::string's const_cast<char*>()' data().这要求std::string数据是连续的,这是标准不需要的,但似乎是所有已知实现的情况.更糟糕的是,如果在文本模式下读取文件,则其std::string大小可能与文件大小不同.
一个完全正确的,符合标准的和便携式解决方案,可以构建使用std::ifstream的rdbuf()进入std::ostringstream,并从那里进入std::string.但是,这可能会复制字符串数据和/或不必要地重新分配内存.所有相关的标准库实现是否足够智能以避免所有不必要的开销?还有另一种方法吗?我是否错过了一些已经提供所需功能的隐藏Boost功能?
请显示您的建议如何实施.
void slurp(std::string& data, bool is_binary)
Run Code Online (Sandbox Code Playgroud)
考虑到上面的讨论.
为了提高从文件读取的性能,我试图将大(几MB)文件的整个内容读入内存,然后使用istringstream来访问信息.
我的问题是,哪个是读取此信息并将其"导入"到字符串流中的最佳方法?这种方法的一个问题(参见下文)是在创建字符串流时,缓冲区被复制,内存使用量增加一倍.
#include <fstream>
#include <sstream>
using namespace std;
int main() {
ifstream is;
is.open (sFilename.c_str(), ios::binary );
// get length of file:
is.seekg (0, std::ios::end);
long length = is.tellg();
is.seekg (0, std::ios::beg);
// allocate memory:
char *buffer = new char [length];
// read data as a block:
is.read (buffer,length);
// create string stream of memory contents
// NOTE: this ends up copying the buffer!!!
istringstream iss( string( buffer ) );
// delete temporary buffer
delete [] buffer;
// close …Run Code Online (Sandbox Code Playgroud) 我想把一个文件读成一个字符串.我正在寻找有效的方法.
使用固定大小的*char缓冲区
我收到了Tony 的回答是什么创建了一个16kb的缓冲区并读入该缓冲区并附加缓冲区,直到没有其他内容可读.我理解它是如何工作的,我发现它非常快.我不明白的是,在答案的评论中,据说这种方式将所有内容复制两次.但据我所知,它只发生在内存中,而不是发生在磁盘上,所以它几乎是不可察觉的.它是从缓冲区复制到内存中的字符串的问题吗?
使用istreambuf_iterator
我收到的另一个答案是使用istreambuf_iterator.代码看起来美观而且极小,但速度极慢.我不知道为什么会这样.为什么那些迭代器这么慢?
使用memcpy()
对于这个问题,我收到的评论是我应该使用memcpy(),因为它是最快的本机方法.但是如何将memcpy()与字符串和ifstream对象一起使用?是不是ifstream应该使用自己的读取功能?为什么使用memcpy()破坏可移植性?我正在寻找与VS2010以及GCC兼容的解决方案.为什么memcpy()不适用于那些?
+还有其他任何有效的方法吗?
对于小的<10 MB二进制文件,你推荐什么,我使用什么shell?
(我不想将这个问题分成几部分,因为我对如何将ifstream读入字符串的不同方式之间的比较更感兴趣)
我需要将jpg文件读取为字符串.我想将此文件上传到我们的服务器,我只是发现API需要一个字符串作为此图片的数据.我在之前的问题中遵循了这些建议,我已经使用c ++将上传图片问到服务器.
int main() {
ifstream fin("cloud.jpg");
ofstream fout("test.jpg");//for testing purpose, to see if the string is a right copy
ostringstream ostrm;
unsigned char tmp;
int count = 0;
while ( fin >> tmp ) {
++count;//for testing purpose
ostrm << tmp;
}
string data( ostrm.str() );
cout << count << endl;//ouput 60! Definitely not the right size
fout << string;//only 60 bytes
return 0;
}
Run Code Online (Sandbox Code Playgroud)
为什么它停在60?60岁时这是一个奇怪的角色,我该怎么做才能将jpg读成一个字符串?
UPDATE
几乎在那里,但在使用建议的方法后,当我将字符串重写为输出文件时,它会失真.发现我还应该指定ofstream处于二进制模式ofstream::binary.完成!
那么ifstream::binary&之间的区别ios::binary是什么 …
如果我想要一个缓冲区read()的内容std::istream,我将不得不首先了解有多少数据可用来知道缓冲区的大小.为了从istream中获取可用字节数,我目前正在做这样的事情:
std::streamsize available( std::istream &is )
{
std::streampos pos = is.tellg();
is.seekg( 0, std::ios::end );
std::streamsize len = is.tellg() - pos;
is.seekg( pos );
return len;
}
Run Code Online (Sandbox Code Playgroud)
同样地,由于std :: istream :: eof()不是一个非常有用的基金AFAICT,为了找出是否istream得到指针在流的末尾,我这样做:
bool at_eof( std::istream &is )
{
return available( is ) == 0;
}
Run Code Online (Sandbox Code Playgroud)
我的问题:
有没有更好的方法来获取可用字节数istream?如果不是在标准库中,也许在boost中?
我想逐行读取文件并捕获一个特定的输入行.为了获得最大性能,我可以通过读取整个文件并使用指针迭代其内容以低级方式执行此操作,但此代码对性能不重要,因此我希望使用更具可读性和类型安全的标准库样式实现.
所以我拥有的是:
std::string line;
line.reserve(1024);
std::ifstream file(filePath);
while(file)
{
std::getline(file, line);
if(line.substr(0, 8) == "Whatever")
{
// Do something ...
}
}
Run Code Online (Sandbox Code Playgroud)
虽然这不是性能关键代码,但我在解析操作之前调用了line.reserve(1024)来排除字符串的多次重新分配,因为读入较大的行.
在std :: getline里面,在添加每行的字符之前删除字符串.我逐步完成了这段代码,以满足自己每次迭代都没有重新分配内存,我发现这些内容让我的大脑充满了热情.
深入string :: erase而不是仅将其size变量重置为零实际上正在调用memmove_s,其指针值会覆盖缓冲区的使用部分,紧跟其后的缓冲区的未使用部分,除了memmove_s正在使用count参数调用零,即请求移动零字节.
问题:
为什么我想在我可爱的循环中调用库函数调用的开销,特别是那个被调用什么都没做的东西?
我自己还没有选择它,但在什么情况下,这个调用实际上什么都不做,但实际上会开始移动大块的缓冲区?
为什么这样做呢?
奖金问题:C++标准库标签是什么?
noob问题!我怎样才能将'整个ifstream'读成stdlib'字符串'?我现在用于所有项目的当前方式浪费了很多时间我认为:
string code;
ifstream input("~/myfile");
char c1=input.get();
while (c1!=EOF)
{
code+=c1;
len++;
c1=input.get();
}
Run Code Online (Sandbox Code Playgroud)
顺便说一下,我更喜欢自己做线和空白管理.
c++ ×8
file-io ×3
string ×3
istream ×2
boost ×1
caching ×1
file-upload ×1
gcc ×1
memory ×1
optimization ×1
std ×1
stl ×1
stream ×1
stringstream ×1