我正在寻找覆盖已经存在的文件的内容。显然,我可以根据这个答案创建一个覆盖旧文件的新文件。但是,我正在编写一个可能会多次执行此操作的程序,并且我想尽可能减少不必要的开销。
所以我的问题是:有没有更好的方法来简单地重写文件本身的内容,而不是编写一个替换旧文件的“新”文件?还是简单地覆盖整个文件内容的开销大致相当于创建新文件然后写入它的开销?(为了记录,这些文件只有 1 KB 大。)
我正在寻找覆盖已经存在的文件的内容。显然,我可以根据这个答案创建一个覆盖旧文件的新文件。但是,我正在编写一个可能会多次执行此操作的程序,并且我想尽可能减少不必要的开销。
所以我的问题是:有没有更好的方法来简单地重写文件本身的内容,而不是编写一个替换旧文件的“新”文件?还是简单地覆盖整个文件内容的开销大致相当于创建新文件然后写入它的开销?(为了记录,这些文件只有 1 KB 大。)
简短的回答:写两个和配置文件。
较长的答案与相当大的挥手:
覆盖文件将涉及以下系统调用:
open
write
close
创建新文件、删除旧文件、重命名新文件将涉及以下系统调用:
open
write
close
unlink
rename
系统调用通常是程序中最慢的部分;一般来说,减少系统调用是加快程序速度的好方法。覆盖一个文件将重新使用操作系统的内部目录条目数据;这可能也会导致一些速度提高。(它们可能很难用具有 VM 开销的语言来衡量......)
您的文件足够小,write()
应该以原子方式处理每个文件,假设您在一次写入中更新整个 1K。(由于您关心性能,这似乎是一个安全的假设。)这确实意味着其他进程不应该看到部分写入,除非在灾难性电源故障和有损挂载选项的情况下。(不常见。)即使面对多次写入,文件重命名方法也能提供一致的文件。
但是,1K 文件是一种非常低效的存储机制;许多文件系统将沿 4k 块写入文件。如果这些数据块只存在于您的应用程序中,那么将它们写入某种容器中可能是有意义的,一次几个。(Quake 派生系统这样做是为了从 zip 文件中读取它们的地图、纹理等,因为巨大的流式 IO 请求比数千个较小的 IO 请求快得多。)当然,如果您的应用程序正在编写,这会更难这些文件供其他应用程序使用,但如果这些文件很少共享,可能仍然值得研究。
您可以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());
只需将其用作链接答案中的示例。让操作系统/文件系统担心取消链接/链接 inode、磁盘上的位置等。如今,绝大多数软件开发都没有充分的理由担心它。
一般来说,不会有太多的开销不会被 CPU/磁盘 i/o 所掩盖。如果您担心磁盘 i/o,请使用内存文件系统(前提是您不需要在发生崩溃时保留文件)或 SATA3 上的速度非常快的 SSD。