【发布时间】:2010-03-29 12:51:13
【问题描述】:
有没有办法在 Java 文件中添加一行,而无需创建临时文件并将所需内容写入其中?
【问题讨论】:
有没有办法在 Java 文件中添加一行,而无需创建临时文件并将所需内容写入其中?
【问题讨论】:
不,没有办法在 Java 中安全做到这一点。 (或 AFAIK,任何其他编程语言。)
没有任何主流操作系统中的文件系统实现支持这种东西,而且你不会发现任何主流编程语言都支持这种特性。
现实世界的文件系统是在将数据存储为固定大小的“块”的设备上实现的。不可能实现一个文件系统模型,您可以将字节插入文件中间而不显着减慢文件 I/O、浪费磁盘空间或两者兼而有之。
涉及文件就地重写的解决方案本质上是不安全的。如果您的应用程序在 prepend / rewrite 过程中被终止或电源中断,您可能会丢失数据。我不建议在实践中使用这种方法。
使用临时文件并重命名。更安全。
【讨论】:
有一种方法,它涉及重写整个文件(但没有临时文件)。正如其他人提到的,没有文件系统支持将内容添加到文件中。下面是一些示例代码,它使用 RandomAccessFile 写入和读取内容,同时将一些内容缓冲在内存中:
public static void main(final String args[]) throws Exception {
File f = File.createTempFile(Main.class.getName(), "tmp");
f.deleteOnExit();
System.out.println(f.getPath());
// put some dummy content into our file
BufferedWriter w = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(f)));
for (int i = 0; i < 1000; i++) {
w.write(UUID.randomUUID().toString());
w.write('\n');
}
w.flush();
w.close();
// append "some uuids" to our file
int bufLength = 4096;
byte[] appendBuf = "some uuids\n".getBytes();
byte[] writeBuf = appendBuf;
byte[] readBuf = new byte[bufLength];
int writeBytes = writeBuf.length;
RandomAccessFile rw = new RandomAccessFile(f, "rw");
int read = 0;
int write = 0;
while (true) {
// seek to read position and read content into read buffer
rw.seek(read);
int bytesRead = rw.read(readBuf, 0, readBuf.length);
// seek to write position and write content from write buffer
rw.seek(write);
rw.write(writeBuf, 0, writeBytes);
// no bytes read - end of file reached
if (bytesRead < 0) {
// end of
break;
}
// update seek positions for write and read
read += bytesRead;
write += writeBytes;
writeBytes = bytesRead;
// reuse buffer, create new one to replace (short) append buf
byte[] nextWrite = writeBuf == appendBuf ? new byte[bufLength] : writeBuf;
writeBuf = readBuf;
readBuf = nextWrite;
};
rw.close();
// now show the content of our file
BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(f)));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
}
【讨论】:
没有。没有“文件内移位”操作,只有离散大小的读写。
【讨论】:
可以通过读取与您要添加的内容长度相等的文件块,写入新内容来代替它,读取后面的块并将其替换为您之前读取的内容,以及以此类推,一直到文件末尾。
但是,不要那样做,因为如果在该过程的中间有任何事情停止(内存不足、断电、恶意线程调用System.exit),数据将会丢失。请改用临时文件。
【讨论】:
您可以将文件内容存储在字符串中,并使用 StringBuilder-Object 预先添加所需的行。您只需先放置所需的行,然后附加文件内容字符串。
不需要额外的临时文件。
【讨论】:
private static void addPreAppnedText(File fileName) {
FileOutputStream fileOutputStream =null;
BufferedReader br = null;
FileReader fr = null;
String newFileName = fileName.getAbsolutePath() + "@";
try {
fileOutputStream = new FileOutputStream(newFileName);
fileOutputStream.write("preappendTextDataHere".getBytes());
fr = new FileReader(fileName);
br = new BufferedReader(fr);
String sCurrentLine;
while ((sCurrentLine = br.readLine()) != null) {
fileOutputStream.write(("\n"+sCurrentLine).getBytes());
}
fileOutputStream.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fileOutputStream.close();
if (br != null)
br.close();
if (fr != null)
fr.close();
new File(newFileName).renameTo(new File(newFileName.replace("@", "")));
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
【讨论】: