[英]Reading a file using fstream
当我尝试将文件读取到缓冲区时,它总是将随机字符附加到缓冲区的末尾。
char* thefile;
std::streampos size;
std::fstream file(_file, std::ios::in | std::ios::ate);
if (file.is_open())
{
size = file.tellg();
std::cout << "size: " << size;
thefile = new char[size]{0};
file.seekg(0, std::ios::beg);
file.read(thefile, size);
std::cout << thefile;
}
int x = 0;
当我在文件中的原始文本是:“ hello”时,输出将变为:“helloýýýý«««««««««
有人可以帮我了解这里发生的事情吗? 谢谢
从C ++文档: http : //cplusplus.com/reference/istream/istream/read
“此函数仅复制数据块,而不检查其内容或在末尾添加空字符 。”
因此,您的字符串会错过结尾的空字符,该字符指示字符串的结尾。 在这种情况下, cout
只会继续打印内存中超出文件范围的thefile
。
在字符串末尾添加'\\0'
。
如果未使用ios::binary
模式打开文件,则不能假设tellg()
返回的位置将为您提供要读取的字符数。 文本模式操作可能会对流执行一些转换(例如:在Windows上,它将在“ \\ n”中的文件中转换“ \\ r \\ n”,因此您可能会发现大小为2,但只读为1)
无论如何, read()
不会添加空终止符。
最后,由于必须添加空终止符,因此必须分配比预期大小还要多的字符。 否则,添加缓冲区时会有缓冲区溢出的风险。
您应该使用gcount()
验证实际读取了多少个字符,并相应地为字符串设置了一个空终止符。
thefile = new char[size + 1]{0}; // one more for the trailing null
file.seekg(0, std::ios::beg);
if (file.read(thefile, size))
thefile[size]=0; // successfull read: all size chars were read
else thefile[file.gcount()]=0; // or less chars were read due to text mode
这是阅读收藏的一种更好的方法:
#include <vector>
#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
#include <cstdint>
#include <iterator>
template<class T>
void Write(std::string const & path, T const & value, std::ios_base::openmode mode)
{
if (auto stream = std::ofstream(path, mode))
{
Write(stream, value);
stream.close();
}
else
{
throw std::runtime_error("failed to create/open stream");
}
}
template<class T>
void Write(std::ostream & stream, T const & value)
{
std::copy(value.begin(), value.end(), std::ostreambuf_iterator<char>(stream));
if (!stream)
{
throw std::runtime_error("failed to write");
}
}
template<class T>
void Read(std::istream & stream, T & output)
{
auto eof = std::istreambuf_iterator<char>();
output = T(std::istreambuf_iterator<char>(stream), eof);
if(!stream)
{
throw std::runtime_error("failed to read stream");
}
}
template<class T>
void Read(std::string const & path, T & output)
{
if (auto stream = std::ifstream(path, std::ios::in | std::ios::binary))
{
Read(stream, output);
stream.close();
}
else
{
throw std::runtime_error("failed to create stream");
}
}
int main(void)
{
// Write and read back text.
{
auto const s = std::string("I'm going to write this string to a file");
Write("temp.txt", s, std::ios_base::trunc | std::ios_base::out);
auto t = std::string();
Read("temp.txt", t);
}
// Write and read back a set of ints.
{
auto const v1 = std::vector<int>() = { 10, 20, 30, 40, 50 };
Write("temp.txt", v1, std::ios_base::trunc | std::ios_base::out | std::ios_base::binary);
auto v2 = std::vector<int>();
Read("temp.txt", v2);
}
return 0;
}
传递一个可迭代的容器,而不是使用“ new”。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.