fopen()
std::string
的函数。行应仅由\n
分隔,而不是其他变体。string ReadWhole()
{
Seek(0);
char *data = new char[GetSize()];
if (1 != fread(data, GetSize(), 1, mFile))
FATAL(Text::Format("Read error: {0}", strerror(errno)));
string ret(data, GetSize());
delete[] data;
return ret;
}
作为参考,这是GetSize
,但它只返回文件的大小(缓存):
int GetSize()
{
if (mFileSize)
return mFileSize;
const int current_position = ftell(mFile);
fseek(mFile, 0, SEEK_END);
mFileSize = ftell(mFile);
fseek(mFile, current_position, SEEK_SET);
return mFileSize;
}
fread()
失败,因为该文件有\r\n
行结尾,并且它们只计为1个字符而不是2个字符,所以它尝试读取的内容超过文件中的字符。
我可以用fgets
修复它,但我想知道是否有更好的方法。感谢。
答案 0 :(得分:3)
fread
返回后无法读取请求的字节数,您应该只检查ferror(mFile)
。如果它是0(假),那么fread
只是停在文件的末尾,你不应该把它作为一个错误。你应该切换两个参数,这样你就可以获得实际读取的字节数:
size_t number_of_bytes_read = fread(data, 1, GetSize(), mFile);
答案 1 :(得分:2)
执行此操作有一种微不足道的惯用方法。
#include <string>
#include <fstream>
#include <sstream>
std::string load_file ( const std::string& path )
{
std::ostringstream contents;
std::ifstream file(path);
if ( !file.is_open() ) {
// process error.
}
contents << file.rdbuf();
return (contents.str());
}
注意:此函数不使用寻求获取输入文件的大小(以字节为单位)。这有(少数)重新分配的缺点,以增加缓冲区,因为有更多的输入可用。它具有与其他std::istream
实现一起工作的优势,这些实现可能无法提前提供内容的大小(即从套接字读取)。
修改:因为您的要求声明使用已经打开且无法更改的FILE*
,您可以实施使用现有{{1}的std::streambuf
实施允许重复使用高级FILE*
和std::istream
操作。
可以使用示例实现right here, on StackOverflow。
P.S。:如果您从未使用过非标准库流缓冲区实现,请按照我指出的实现快速概述如何编写函数。
std::ostream
答案 2 :(得分:0)
你可以分配一个固定大小的缓冲区,并且最多可以从文件中重复fread
并将其附加到string::apeend(char*, size_type)
的字符串中。
答案 3 :(得分:0)
只需使用fgetc()
一次读取一个字符。您可以使用特殊情况将'\ r \ n'结尾转换为普通'\ n'。
std::string ReadWhole() {
std::string ret;
char prev = 0, c;
while ((c = fgetc(mFile)) != EOF) {
if (prev == '\r' && c == '\n') {
ret.erase(ret.rend()); // erase the previous \r
}
ret += c;
prev = c;
}
return ret;
}