我想要覆盖已经存在的文件的内容。显然,我可以根据this answer创建一个覆盖旧文件的新文件。但是,我正在编写一个可能会执行此操作的程序,并且我希望尽可能减少不必要的开销。
所以我的问题是:有没有更好的方法来简单地重写文件本身的内容,而不是编写一个替换旧文件的“新”文件?或者是简单地覆盖整个文件内容的开销大致相当于创建新文件然后写入它的开销? (对于记录,这些文件只有1 KB大。)
答案 0 :(得分:4)
简短的回答:写两个和简介。
更长的答案,挥手相当:
覆盖文件将涉及以下系统调用:
open
write
close
创建新文件,删除旧文件以及重命名新文件将涉及以下系统调用:
open
write
close
unlink
rename
系统调用通常是程序中最慢的部分;通常,减少系统调用是加速程序的好方法。覆盖一个文件将重用操作系统的内部目录条目数据;这可能也会带来一些速度提升。 (它们可能很难用VM开销的语言来衡量......)
您的文件足够小,每个write()
应该以原子方式处理,假设您在一次写入中更新整个1K。 (因为你关心性能,这似乎是一个安全的假设。)这确实意味着其他进程不应该看到部分写入,除非是灾难性的powerfailures和有损挂载选项。 (不常见。)即使面对多次写入,文件重命名方法也会提供一致的文件。
但是,1K文件是一种效率很低的存储机制;许多文件系统将沿4k块写入文件。如果这些数据块仅存在于您的应用程序中,那么在某种类型的容器中编写它们可能是有意义的,一次几个。 (Quake派生系统用它来读取zip文件中的地图,纹理等等,因为巨大的流式IO请求远远快于数千个较小的IO请求。)当然,如果您的应用程序正在编写,这将更难这些文件供其他应用程序使用,但如果文件很少共享,可能仍值得调查。
答案 1 :(得分:1)
您可以使用RandomAccessFile
这是一个简短的示例:
// create a new RandomAccessFile with filename test
RandomAccessFile raf = new RandomAccessFile("c:/test.txt", "rw");
// write something in the file
raf.writeUTF("Hello World");
// set the file pointer at 0 position
raf.seek(0);
// print the string
System.out.println("" + raf.readUTF());
// print current length
System.out.println("" + raf.length());
// set the file length to 30
raf.setLength(30);
// print the new length
System.out.println("" + raf.length());
答案 2 :(得分:0)
在链接的答案中使用它作为示例。让操作系统/文件系统担心取消链接/链接inode,磁盘上的位置等等。现在很少有理由担心绝大多数软件开发。
通常,不会有太多的开销没有被CPU /磁盘i / o黯然失色。如果您担心磁盘i / o,请使用内存文件系统(假设您不需要在发生崩溃时保留文件)或SATA3上的速度非常快。