2

我正在实现一个非常简单的文件数据库。我有2个基本操作:

void Insert(const std::string & i_record)
{
   //create or append to the file
    m_fileStream.open(m_fileName.c_str(), std::ios::out | std::ios::app);

    if (m_fileStream.is_open())
    {
        m_fileStream << i_record << "\n";
    }

    m_fileStream.flush();
    m_fileStream.close();
}

/*
* Returns a list with all the items in the file.
*/
 std::vector<std::string> SelectAll()
 {
    std::vector<std::string> results;

    m_fileStream.open(m_fileName.c_str(), std::ios::in);

    std::string line;
    if (m_fileStream.is_open())
    {
        while (!m_fileStream.eof())
        {
            getline (m_fileStream, line);
            results.push_back(line);

        }
    }

    m_fileStream.close();

    return results;
 }    

该类将 m_fileStream 和 m_fileName 作为私有成员。

好的 - 这是问题所在:

如果我这样做:

db->Insert("a");
db->SelectAll();
db->Insert("b");

最终结果是文件将包含“a”;为什么?

注意:似乎 getline() 将设置失败位。但为什么?

4

2 回答 2

4

改变

    while (!m_fileStream.eof())
    {
        getline (m_fileStream, line);
        results.push_back(line);

    }

    while (getline (m_fileStream, line))
    {
        results.push_back(line);
    }

否则最后你会得到一个额外的空行。eof()仅当您尝试读取文件末尾之后才会返回 true,而不是仅当下一次读取超出文件末尾时才会返回。

它设置了failbit因为getline尝试从流中提取字符。如果没有剩下的字符(并且'\n'还没有看到),stream.get(c)一个字符将设置failbit. 然后getline将设置eofbit然后.eof()将返回true,并且您的循环退出。

如果您不想failbit设置,则将您的条件从更改!stream.eof()stream.peek() != EOF(并确保文件中有一个尾随换行符)。

现在这也是您问题的解决方案:.close()不是.clear()您的流,因此failbit如果您重新打开文件,仍然会设置。读完你的东西后打电话stream.clear(),然后它就可以工作了。

于 2008-11-15T17:01:57.793 回答
1

我认为 litb 非常成功。但只是添加我的 0.02 美元:

1)我一直喜欢:

while ( stream && (stream.peek() != EOF) )  {...}

因为可能会发生除 EOF 之外的 [坏] 事件。

(而且,正如 litb 所提到的,peek()!=EOF 解决了流不设置 EOF 的问题,直到我们尝试读取末尾。)

.

2)由于“m_fileStream”在这两种方法中都被打开、读取/写入/刷新和关闭......

为什么不在堆栈上本地声明呢?这样做可以确保没有以前的状态问题留下来搞砸你。而且你访问磁盘,所以效率可能不是最大的问题......

此外,你可以偷懒:

ifstream stream ( m_fileName.c_str() );
ASSERT( stream, !=, NULL );  // Uses my own ASSERT macro && stream.operator().
while ( stream && (stream.peek() != EOF) )  {...}
于 2008-11-15T18:36:53.423 回答