附加到CSV文件,我可以使用seek来确定是否应该写入标题吗?有更好的方法吗?

Appending to CSV file, can I use seek to determine if header should be written? Is there a better way?

提问人:alec 提问时间:11/15/2020 最后编辑:alec 更新时间:11/15/2020 访问量:126

问:

我必须生成一些 CSV 文件并将它们写入磁盘。不幸的是,我一次只能得到一行文件。 我必须每秒进行大量写入,所以我希望我的程序尽可能高效(尽量减少磁盘操作)

我目前有以下 ruby 代码来构建 csv:

def add_line(doc)
    File.open("myfile.csv", "a") do |f|
        f.seek(0, IO::SEEK_END)                            # Move cursor to end of file (is this costly?)
        f.write(doc.keys.join(",") + "\n") if f.pos() == 0 # Write header if cursor position is 0
        f.write(doc.values.join(",") + "\n")               # Write CSV line
    end
end

# Write line to file
add_line({
    key1: "value1",
    key2: "value2",
    key3: "value3"
})

确定是否应该写入标头的最有效方法是什么?我可以先检查文件的大小,如果它是 0,则写标题。 使用效率更高吗? 有没有更好的方法来实现这一目标?seek

有关用例的更多背景信息: 我正在将这些 CSV 文件写入 Ceph 卷(分布式文件系统),并且我正在尝试尽可能地减少文件系统的压力(因为这些写入量将非常大)

我希望 ruby 可以在以追加模式打开时指示是否必须创建文件,因为它可以使我不必进行这种额外的检查。

谢谢!

Ruby 性能 CSV 文件 IO

评论

1赞 Cary Swoveland 11/15/2020
是否可以存在零字节文件,或者您在创建时是否始终添加内容(至少是标题)?如果是后者,只需检查文件是否存在。如果它不写入标头,如果需要,可以写入更多。你不需要做任何寻找;Append 选项会将写入指针放在文件的末尾。您不使用 CSV 方法有什么特殊原因吗?"a"
0赞 alec 11/15/2020
谢谢@CarySwoveland。文件不应为 0 字节 -- 它们要么有一行或多行,要么为空。我想过检查文件是否存在,但我正在将文件写入 Ceph 卷,我担心每次写入行时都执行 File.exist 和 File.open 会给分布式文件系统带来太大的压力。我做 f.seek 的唯一原因是因为我想获取光标位置以确定文件是否为空。出于某种原因,除非首先调用 seek,否则 f.tell() 和 f.pos() 总是在追加模式下返回 0。
0赞 alec 11/15/2020
但是,我认为这个解决方案(使用 f.seek)并不比使用 File.exists 好,因为我怀疑 SEEK_END 本质上也在后台执行 fstat。理想情况下,我希望追加模式下的 File.open 将指示文件是否存在或必须创建,但我认为如果不进行单独检查,就没有办法获取该信息。
0赞 Konstantin Strukov 11/15/2020
Chicking via 我看到您的方法 ( + ) 需要在引擎盖下调用两个系统 - 而不是在 .另一方面,与(返回 0)返回仓位本身不同,所以我想需要一个(没有检查,但如果没有,我会感到惊讶)......straceseekposlseekfstatf.sizeIO#seekIO#sysseek<write headers> if f.sysseek(0, IO::SEEK_END) == 0lseek

答: 暂无答案