这是在Java中重写文件内容的最佳方式吗?

50

我想重写一个文件的内容。

目前我想到的做法是:

  1. 保存文件名
  2. 删除原有文件
  3. 创建一个同名的新空文件
  4. 将要写入的内容写入新的空文件中

这是最好的方法吗?还是有更直接的方法,即不需要删除和创建文件,而只需改变文件的内容?

8个回答

94

使用FileOutputStream覆盖文件foo.log:

File myFoo = new File("foo.log");
FileOutputStream fooStream = new FileOutputStream(myFoo, false); // true to append
                                                                 // false to overwrite.
byte[] myBytes = "New Contents\n".getBytes(); 
fooStream.write(myBytes);
fooStream.close();
或者使用FileWriter:
File myFoo = new File("foo.log");
FileWriter fooWriter = new FileWriter(myFoo, false); // true to append
                                                     // false to overwrite.
fooWriter.write("New Contents\n");
fooWriter.close();

在关闭FileWriter之后,您需要关闭File对象吗? - AnnanFay
1
@Annan:Java的File对象不需要打开,因此不需要关闭...请参见https://dev59.com/nW445IYBdhLWcg3wq8BY的答案。 - Stobor
3
如果之前的内容比新内容要长,那么多余的部分会被删除还是在文件末尾找到,在其中写入少于应该删除的内容? - Daren
4
如果我们没有指定任何值,它将变为 false 并覆盖旧文件。 - Mr.Q
1
感谢 @pmartin8 的改进。 - Stobor
显示剩余3条评论

12

我强烈建议使用Apache Common的FileUtil来完成这个任务。 我发现这个包非常有价值。它易于使用,同样重要的是,当您过一段时间后再回来阅读/理解时,也很容易阅读/理解。

//Create some files here
File sourceFile = new File("pathToYourFile");
File fileToCopy = new File("copyPath");

//Sample content
org.apache.commons.io.FileUtils.writeStringToFile(sourceFile, "Sample content");

//Now copy from source to copy, the delete source.
org.apache.commons.io.FileUtils.copyFile(sourceFile, fileToCopy);
org.apache.commons.io.FileUtils.deleteQuietly(sourceFile);

更多信息可以在此处找到: http://commons.apache.org/io/api-release/org/apache/commons/io/FileUtils.html


5

请参考:java.io.RandomAccessFile

你需要以读写模式打开一个文件,代码如下:

RandomAccessFile raf = new RandomAccessFile("filename.txt", "rw");
String tmp;
while (tmp = raf.readLine() != null) {
    // Store String data
}
// do some string conversion
raf.seek(0);
raf.writeChars("newString");

我误读了问题,以为需要重写文件,例如修改内容,而不是完全用新内容替换。 - drfloob
1
无论如何,我正在寻找覆盖文件特定部分的方法,这就是答案! - fyts

4

从Java 7开始,使用新的文件API,使用java.nio.file.Files类非常简单:

Files.write(Path.of("foo.log"), "content".getBytes(StandardCharsets.UTF_8));

Java 8中新增了写入UTF-8字符串列表的功能:

Files.write(Path.of("foo.log"), List.of("content line 1", "content line 2"));

Java 11中新增了用UTF-8编写字符串的功能:

Files.writeString(Path.of("foo.log"), "content");

2

除非您只是在末尾添加内容,否则这样做是合理的。如果您要追加,请使用带有追加构造函数的FileWriter

稍微好一点的顺序是:

  1. 生成新文件名(例如foo.txt.new)
  2. 将更新后的内容写入新文件。
  3. 使用原子重命名从foo.txt.new重命名为foo.txt

不幸的是,renameTo不能保证进行原子重命名。点击此处了解更多信息。


1

有时候,人们可能想要保留一个巨大的空文件,以避免操作系统按需分配空间的额外成本。这通常由数据库、虚拟机和批处理程序完成,这些程序处理和写入大量数据。这将显着提高应用程序的性能。在这些情况下,编写新文件并重命名它实际上并没有帮助。相反,必须填充空文件。这就是需要使用覆盖模式的时候。


1
在下面的例子中,“false”会导致文件被覆盖,而“true”则会导致相反的结果。
File file=new File("C:\Path\to\file.txt");
DataOutputStream outstream= new DataOutputStream(new FileOutputStream(file,false));
String body = "new content";
outstream.write(body.getBytes());
outstream.close(); 

3
好奇!引入DataOutputStream有什么好处? - Adeel Ansari
到目前为止,size()和writeUTF()方法对我非常有用,所以我选择使用它。在使用DataOutputStream写入字符串之前,您也可以不将其转换为字节。 - Sev
DataInputStream和DataOutputStream是用于处理某种二进制文件的专门类,不应该用于文本文件。读写文本文件的正确方式是使用Reader和Writer:FileReader和FileWriter使用平台默认编码,而InputStreamReader和OutputStreamWriter允许您指定编码(如UTF-8)。 - Alan Moore

0

Guava Files.write "使用字节数组的内容覆盖文件":

Files.write(bytes, new File(path));

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接