我正在寻找覆盖已存在的文件的内容。显然,我可以创建一个覆盖旧文件的新文件,按照this answer。但是,我正在编写一个程序,这个程序可能会进行很多次,我想尽可能地减少不必要的开销。有没有更好的方法来覆盖文件内容?
所以我的问题是:是否有更好的方法来简单地重写文件本身的内容,而不是写一个替换旧文件的“新”文件?或者是简单地覆盖整个文件内容大致相当于创建新文件并写入它的开销的开销? (为了记录,这些文件只有1 KB大。)
我正在寻找覆盖已存在的文件的内容。显然,我可以创建一个覆盖旧文件的新文件,按照this answer。但是,我正在编写一个程序,这个程序可能会进行很多次,我想尽可能地减少不必要的开销。有没有更好的方法来覆盖文件内容?
所以我的问题是:是否有更好的方法来简单地重写文件本身的内容,而不是写一个替换旧文件的“新”文件?或者是简单地覆盖整个文件内容大致相当于创建新文件并写入它的开销的开销? (为了记录,这些文件只有1 KB大。)
简短的回答:写两个和配置文件。
带有较长的答案相当挥手:
覆盖一个文件会涉及到以下系统调用:
open
write
close
创建一个新的文件,删除旧文件,然后重命名新的文件将包括以下系统调用:
open
write
close
unlink
rename
系统调用通常程序的最慢的部分;一般来说,减少系统调用是加速程序的好方法。覆盖一个文件将重新使用操作系统的内部目录条目数据;这可能也会导致一些速度的提升。 (它们可能难以用虚拟机开销语言来衡量......)
您的文件足够小,以至于每个write()
都应该以原子方式处理,假设您在一次写入中更新整个1K。 (因为你关心性能,这似乎是一个安全的假设。)这意味着其他进程不应该看到部分写入,除非发生灾难性电源故障和有损挂载选项。 (不常见)。即使面对多次写入,文件重命名方法也会提供一致的文件。
但是,1K文件是一个相当低效的存储机制;许多文件系统将沿着4k块写入文件。如果这些数据块仅存在于您的应用程序中,则可以将它们写入容器,这些容器可以是某种类型的,每次可以多个。 (因为巨大的流IO请求比数千个更小的IO请求要快得多,因此Quake派生系统会从zip文件中读取它们的地图,纹理等等。)当然,如果您的应用程序正在编写这些文件可供其他应用程序使用,但是如果这些文件很少共享,可能仍值得研究。
只是用它作为链接答案的一个例子。让操作系统/文件系统担心取消链接/链接索引节点,磁盘上的位置等等。现在很少有很好的理由担心绝大多数软件开发。
一般来说,CPU /磁盘I/O不会造成太多开销。如果您关心磁盘I/O,请在SATA3上使用内存文件系统(假设您不需要在发生崩溃时保留文件)或非常快速的SSD。
你可以在这里使用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());
但是,只有当您以随机访问的方式访问数据时,并且只有在您使用完全相同长度的数据替换精确长度的数据时。 –
@ialiashkevich真棒,这正是我正在寻找的选择。这些文件总是大致相同的长度(它们基本上只是在特定模式下的数字),所以这似乎可以工作。但是现在,原来的问题是:什么开销较少 - 你的方法,或者我在原文中链接到的答案的方法? – MattS
如果只重写文件的一部分,则RandomAccessFile的开销较小。重写整个文件将与原始文章的答案相同。
由于您的程序调用了另一个程序,它将某种格式的文件作为输入,因此不应该担心文件写入开销,调用另一个程序会占用系统的大部分资源。
我会建议在多线程中同时写入文件和调用程序,在这种情况下,您可以获得最大的硬件性能。 –
ialiashkevich
你了解文件如何存储在磁盘上,以及如何限制他们如何处理,是否正确? –
我不确定我明白你在问什么。我有一定的理解,但我不会说我是磁盘数据存储方面的专家。我是第二年和第三年的计算机科学专业的学生(这不是家庭作业),所以我们已经介绍了一些文件存储,但是在我的课堂上并没有多少东西。 – MattS
如何使用像[Redis](http://redis.io/)这样的数据库或键值存储而不是文件? –