写入所有但前N行的流而不会破坏目标流

时间:2014-11-17 23:39:56

标签: c++ windows newline

如何在不破坏目标流的情况下编写除流的前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");
}

1 个答案:

答案 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()处于启用状态,则会重新抛出捕获的异常。

因此,如果至少复制一个字符,它们只是等效的。