3

我有一些内部文件,只能附加到每个附加\n字符添加到文件之后。但从理论上讲,附加到文件可能会失败并损坏。这就是为什么每次打开文件时我都想在最后一个 EOL 之后寻找它的最后一个有效位置。此代码将执行此操作:

// Not using ios::app instead of ios::ate | ios::out because it will
// put print pointer to the EOF every time before writing.
fstream file(name.c_str(), ios::binary | ios::ate | ios::out | ios::in);
if(!file.is_open()) {
    cerr << "Error in oppening file " << name << endl;
    exit(EXIT_FAILURE);
} else {
    while(0 != file.tellp()) //if file is not empty
    {
        file.seekg(-1, ios_base::cur);
        if(0 == file.tellg() || file.get() == '\n') {
            break;
        }
        file.seekg(-1, ios_base::cur);
    }
    file.seekp(of.tellg());
}
//{1}
//Use file for appending to...

但是如果应该附加到文件的部分的长度小于从文件中最后一个 EOL 字符开始的部分的长度,则它不会正常工作。这就是为什么{1}我想删除从 file.tellp() 开始到最后的文件内容。

我怎样才能做到这一点?

4

2 回答 2

1

你不能,便携。不同的系统有不同的方法来做到这一点,但通常只在系统文件句柄上。缩短文件的唯一保证方法是将其复制到另一个文件中,而不是复制您不想要的文件,然后删除原始文件并重命名新文件。

如果它是一个文本文件(不是二进制文件),并且您在 Windows 下,则在该位置写入 0x1A 可能会起作用。然而,在 Unix 下没有类似的东西。

在您的情况下,仅覆盖结尾就足够了。如果情况变得更糟,并且您需要附加的内容不足以覆盖尾随数据,您可能会尝试用一些无害且易于识别的内容覆盖它,例如'\0'. (正式地,将这样的内容或 0x1A 写入文本文件是未定义的行为。实际上,它会起作用。)

(当我不得不解决类似的问题时,我采用了在记录的开头写入块的 CRC 的策略;在读取时,我忽略了 CRC 错误的任何内容。)

于 2012-04-20T10:09:54.830 回答
1

没有可移植的方法来做到这一点(有关更全面的解释,请参阅 James Kanze 更好的答案)。

如果您在 POSIX 系统上,那么您可以使用ftruncate(参见此处)将文件的长度设置为特定长度。我不知道 C++ 等价物(有关更多信息,请参阅此问题)

于 2012-04-20T09:49:52.887 回答