将数据附加到 C++ 中的文件,但如果程序重新执行则覆盖
Append data to a file in C++ but overwrite if the program is re-executed
我想使用如下函数将数据附加到文件:
void Fill( string fileName ){
ofstream outputFile(fileName, ofstream::out | ofstream::app);
outputFile << data1 << " " << data2 << endl;
outputFile.close();
}
如果满足某些条件,此函数将在循环中用于写入不同的文件。但我想在程序为 运行 时从空文件开始,即不附加到旧数据。我怎样才能做到这一点?
希望我说清楚了。
谢谢!
您传递给函数的 ofstream::app
参数表示您想要追加到一个文件(如果它已经存在)。默认行为是您正在寻找的。删除那部分,
所以:
ofstream outputFile(fileName, ofstream::out);
使用 ofstream::trunc
打开文件,然后将该文件流传递给您的 Fill
函数(而不是文件名字符串)以附加新数据。
这是一个不完整的例子:
void Fill(ofstream& outputFile) {
outputFile << data1 << " " << data2 << endl;
}
int main() {
ofstream outputFile(fileName, ofstream::out | ofstream::trunc);
Fill(outputFile);
outputFile.close();
}
(假设您正在将其他数据写入其他地方的文件。如果您只是从 Fill
函数中访问此文件,那么大卫的回答只是从 Fill
好多了。
最简单的解决方案是打开您的程序使用的所有文件,而不是 std::ofstream::app 在您在开始时调用一次以截断它们的某些函数中。
void resetFiles()
{
static char * fileNames[] = {
// Fill this with filenames of the files you want to truncate
};
for( int i = 0; i < sizeof( fileNames ) / sizeof( fileNames[ 0 ] ); ++i )
std::ofstream( fileNames[ i ] );
}
int main( int argc, char ** argv )
{
resetFiles();
...
}
编辑:由于您确实指定您正在寻找更优雅的解决方案,这就是我想出的。基本上你声明一个新的 class 继承自 std::ofstream 静态 std::map< std::string, bool > 成员称为记录。您添加一个允许您指定文件名的构造函数。然后它通过检查记录中是否存在键 fileName 来查找文件是否已经打开一次。如果不是,它将使用 std::ofstream::trunc 打开它并将 record[ fileName ] 设置为 true。这样,当文件第二次打开时,它知道它必须用 std::ofstream::app.
打开它
class OutFile : public std::ofstream
{
static std::map< std::string, bool > record;
// Helper function
static std::ios_base::openmode hasBeenOpened( std::string fileName )
{
// Test if the key is present
if( record.find( fileName ) == record.end() )
{
record[ fileName ] = true;
return std::ofstream::trunc;
}
else
{
return std::ofstream::app;
}
}
public:
OutFile( const char * filename )
: std::ofstream( filename, hasBeenOpened( std::string( filename ) ) ) {}
};
// Don't forget to initialize record
map< std::string, bool > OutFile::record;
我想使用如下函数将数据附加到文件:
void Fill( string fileName ){
ofstream outputFile(fileName, ofstream::out | ofstream::app);
outputFile << data1 << " " << data2 << endl;
outputFile.close();
}
如果满足某些条件,此函数将在循环中用于写入不同的文件。但我想在程序为 运行 时从空文件开始,即不附加到旧数据。我怎样才能做到这一点? 希望我说清楚了。 谢谢!
您传递给函数的 ofstream::app
参数表示您想要追加到一个文件(如果它已经存在)。默认行为是您正在寻找的。删除那部分,
所以:
ofstream outputFile(fileName, ofstream::out);
使用 ofstream::trunc
打开文件,然后将该文件流传递给您的 Fill
函数(而不是文件名字符串)以附加新数据。
这是一个不完整的例子:
void Fill(ofstream& outputFile) {
outputFile << data1 << " " << data2 << endl;
}
int main() {
ofstream outputFile(fileName, ofstream::out | ofstream::trunc);
Fill(outputFile);
outputFile.close();
}
(假设您正在将其他数据写入其他地方的文件。如果您只是从 Fill
函数中访问此文件,那么大卫的回答只是从 Fill
好多了。
最简单的解决方案是打开您的程序使用的所有文件,而不是 std::ofstream::app 在您在开始时调用一次以截断它们的某些函数中。
void resetFiles()
{
static char * fileNames[] = {
// Fill this with filenames of the files you want to truncate
};
for( int i = 0; i < sizeof( fileNames ) / sizeof( fileNames[ 0 ] ); ++i )
std::ofstream( fileNames[ i ] );
}
int main( int argc, char ** argv )
{
resetFiles();
...
}
编辑:由于您确实指定您正在寻找更优雅的解决方案,这就是我想出的。基本上你声明一个新的 class 继承自 std::ofstream 静态 std::map< std::string, bool > 成员称为记录。您添加一个允许您指定文件名的构造函数。然后它通过检查记录中是否存在键 fileName 来查找文件是否已经打开一次。如果不是,它将使用 std::ofstream::trunc 打开它并将 record[ fileName ] 设置为 true。这样,当文件第二次打开时,它知道它必须用 std::ofstream::app.
打开它class OutFile : public std::ofstream
{
static std::map< std::string, bool > record;
// Helper function
static std::ios_base::openmode hasBeenOpened( std::string fileName )
{
// Test if the key is present
if( record.find( fileName ) == record.end() )
{
record[ fileName ] = true;
return std::ofstream::trunc;
}
else
{
return std::ofstream::app;
}
}
public:
OutFile( const char * filename )
: std::ofstream( filename, hasBeenOpened( std::string( filename ) ) ) {}
};
// Don't forget to initialize record
map< std::string, bool > OutFile::record;