如何在不破坏目标流的情况下编写除流的前N行以外的所有行?
例如,当源具有n-1或更少的行并且源具有n + 1或更多行时,以下工作正常,但是当源具有n行时有时会失败:
void copy_all_but_first_n_lines(std::ifstream& source, std::ofstream& dest, size_t n)
{
for (size_t i=0; i<n; ++i)
{
std::string line;
std::getline(source, line);
}
if (source.good()) dest << source.rdbuf();
if (!dest.good()) throw std::runtime_error("destination turned bad after writing remainder of source");
}
如果源只有n行,则目标有时会设置failbit。
仅当源具有尾随换行符时才设置此失败位。我在Windows上进行测试,在十六进制编辑器中,我看到带有尾随换行符和n行的文件导致目标流设置了failbit,但是没有结束行的n行的文件没有结果在failbit集中。我正在测试的所有文件都有换行符“\ r \ n”。
我尝试在文本和二进制模式下打开流,但这并未改变行为。
如果我将代码更改为使用std::copy
而不是编写rdbuf
,则无论是否存在尾随换行符,它都会起作用。根据{{3}},这两个应该是等价的 - 为什么在std :: copy成功时编写rdbuf失败?
void copy_all_but_first_n_lines(std::ifstream& source, std::ofstream& dest, size_t n)
{
for (size_t i=0; i<n; ++i)
{
std::string line;
std::getline(source, line);
}
if (source.good())
{
std::istreambuf_iterator<char> begin(source);
std::istreambuf_iterator<char> end;
std::ostreambuf_iterator<char> destination(dest);
std::copy(begin, end, destination);
}
if (!dest.good()) throw std::runtime_error("destination turned bad after writing remainder of source");
}
答案 0 :(得分:2)
看看标准:
basic_ostream<charT,traits>& operator<<(basic_streambuf<charT,traits>* sb);
7 效果:表现为无格式输出功能(如27.7.3.7第1段所述)。后 如果
sb
为空调用setstate(badbit)
(可能会抛出ios_base::failure
),则构造sentry对象。
8从sb
获取字符并将其插入*this
。从sb
读取字符并插入,直到出现以下任何一种情况:
- 文件结尾出现在输入序列上;
- 在输出序列中插入失败(在这种情况下,不会提取要插入的字符);
- 从某人那里获取角色时发生异常。
9如果函数不插入任何字符,则调用
setstate(failbit)
(可能会抛出ios_base::failure
(27.5.5.4))。如果在提取字符时抛出异常,则函数会将failbit
设置为错误状态,如果failbit
中的exceptions()
处于启用状态,则会重新抛出捕获的异常。
因此,如果至少复制一个字符,它们只是等效的。