首先,一些细节:
假设我有一些名为 cpp_code 的C ++代码:
一些简化的R代码将是:
for(i in 1:10000)
{
system(paste0("echo ", toString(i), " | ./cpp_code")) ## produces out.csv
output[i,,] <- read.csv("out.csv") ## reads out.csv
}
我的问题:
99%的时间,一切正常。但是,我时不时地收到一些不寻常的.tmp文件,例如:“out.csv.tmp_a0ac9806ff7f0000703a”。这些.tmp文件只出现一秒左右,然后突然消失。
问题:
因为计算不是我的主要学科,所以请放轻松。
非常感谢你的时间。
答案 0 :(得分:4)
许多程序将其输出写入临时文件,然后将其重命名为目标文件。这通常是为了避免在写入过程中杀死进程时留下半写输出文件。通过使用临时文件,可以将文件原子重命名为输出文件名,确保:
请注意,通常仍会存在一些竞争条件,例如,输出文件被删除但临时文件未重命名,但上述两个结果中的一个是一般目标。
答案 1 :(得分:3)
我相信您在.save
中使用armadillo
功能。
http://arma.sourceforge.net/docs.html#save_load_field
您应该看到两个功能
include/armadillo_bits/diskio_meat.hpp
。在save_raw_ascii
中,它首先将数据存储到diskio::gen_tmp_name
的文件名中,如果save_okay
,则按safe_rename
重命名。如果safe_okay
或safe_rename
失败,您将看到临时文件。临时文件名选择为filename + .tmp_ + some hex value from file name
。
//! Save a matrix as raw text (no header, human readable).
//! Matrices can be loaded in Matlab and Octave, as long as they don't have complex elements.
template<typename eT>
inline
bool
diskio::save_raw_ascii(const Mat<eT>& x, const std::string& final_name)
{
arma_extra_debug_sigprint();
const std::string tmp_name = diskio::gen_tmp_name(final_name);
std::fstream f(tmp_name.c_str(), std::fstream::out);
bool save_okay = f.is_open();
if(save_okay == true)
{
save_okay = diskio::save_raw_ascii(x, f);
f.flush();
f.close();
if(save_okay == true)
{
save_okay = diskio::safe_rename(tmp_name, final_name);
}
}
return save_okay;
}
//! Append a quasi-random string to the given filename.
//! The rand() function is deliberately not used,
//! as rand() has an internal state that changes
//! from call to call. Such states should not be
//! modified in scientific applications, where the
//! results should be reproducable and not affected
//! by saving data.
inline
std::string
diskio::gen_tmp_name(const std::string& x)
{
const std::string* ptr_x = &x;
const u8* ptr_ptr_x = reinterpret_cast<const u8*>(&ptr_x);
const char* extra = ".tmp_";
const uword extra_size = 5;
const uword tmp_size = 2*sizeof(u8*) + 2*2;
char tmp[tmp_size];
uword char_count = 0;
for(uword i=0; i<sizeof(u8*); ++i)
{
conv_to_hex(&tmp[char_count], ptr_ptr_x[i]);
char_count += 2;
}
const uword x_size = static_cast<uword>(x.size());
u8 sum = 0;
for(uword i=0; i<x_size; ++i)
{
sum += u8(x[i]);
}
conv_to_hex(&tmp[char_count], sum);
char_count += 2;
conv_to_hex(&tmp[char_count], u8(x_size));
std::string out;
out.resize(x_size + extra_size + tmp_size);
for(uword i=0; i<x_size; ++i)
{
out[i] = x[i];
}
for(uword i=0; i<extra_size; ++i)
{
out[x_size + i] = extra[i];
}
for(uword i=0; i<tmp_size; ++i)
{
out[x_size + extra_size + i] = tmp[i];
}
return out;
}
答案 2 :(得分:0)
“黑暗猎鹰”假设是完全正确的:当调用save
时,Armadillo会创建一个临时文件,保存数据,然后将文件重命名为最终名称。
可以看到in the source code(这是save_raw_ascii
,但其他save*
函数类似地工作):
const std::string tmp_name = diskio::gen_tmp_name(final_name);
std::fstream f(tmp_name.c_str(), std::fstream::out);
bool save_okay = f.is_open();
if(save_okay == true)
{
save_okay = diskio::save_raw_ascii(x, f);
f.flush();
f.close();
if(save_okay == true)
{
save_okay = diskio::safe_rename(tmp_name, final_name);
}
}
对safe_rename
的评论说明了这一点:
安全地重命名文件。 在重命名之前,请测试我们是否可以写入最终文件。 这应该阻止:
- 覆盖写保护的文件,
- 覆盖目录。
醇>
值得注意的是,这会不阻止竞争条件。