Есть ли способ добавить строку к файлу в Java, не создавая временный файл и записывая в него необходимый контент?
Подготовить строки к файлу на Java
Ответ 1
Нет, в Java нет возможности сделать это БЕСПЛАТНО.
Никакая реализация файловой системы в любой основной операционной системе не поддерживает эту функцию, и вы не найдете эту функцию, поддерживаемую на каких-либо основных языках программирования.
Файловые системы реального мира реализованы на устройствах, которые хранят данные в виде блоков фиксированного размера. Невозможно реализовать модель файловой системы, в которую вы можете вставлять байты в середину файла без значительного замедления ввода-вывода файлов, потери пространства на диске или и того и другого.
Решения, связанные с переписыванием файла на месте, по своей сути являются небезопасными. Если ваше приложение убито или сила умирает в середине процесса prepend/rewrite, вы, вероятно, потеряете данные. Я бы не рекомендовал использовать этот подход на практике.
Использовать временный файл. Это безопаснее.
Ответ 2
Есть способ, он включает в себя переписывание всего файла (но без временного файла). Как уже упоминалось, никакая файловая система не поддерживает добавление содержимого в файл. Вот пример кода, который использует 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);
}
}
Ответ 3
Нет. Нет операций "внутри файла", только чтение и запись дискретных размеров.
Ответ 4
Да, есть. Просто прочитайте файл полностью в памяти Java, а затем полностью запишите его в тот же файл с новыми добавленными строками. Это, однако, не так эффективно и небезопасно для памяти (больше риска потерять данные во время сбоя), поэтому я бы действительно подумал о том, чтобы сохранить временный файловый подход. Чтобы ускорить работу, вы можете просто rename после закрытия, чтобы вам не нужно было передавать данные вперед и назад для два раза.
Ответ 5
Вы можете сохранить содержимое файла в String и добавить нужную строку с помощью StringBuilder-Object. Вам просто нужно сначала поместить нужную строку, а затем добавить файл-контент-String.
Не требуется дополнительный временный файл.
Ответ 6
Это можно было бы сделать, читая фрагмент файла равной длины тому, что вы хотите добавить, записывая новый контент вместо него, читая более поздний фрагмент и заменяя его тем, что вы читали ранее, и и так далее, сбрасывая вниз до конца файла.
Однако не делайте этого, потому что, если в середине этого процесса произойдет что-либо (из-за нехватки памяти, перебой питания, вызов изгоев потока System.exit
), данные будут потеряны. Вместо этого используйте временный файл.
Ответ 7
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();
}
}
}