Вставка текста в существующий файл через Java - PullRequest
24 голосов
/ 14 ноября 2008

Я хотел бы создать простую программу (на Java), которая редактирует текстовые файлы - особенно ту, которая выполняет вставку произвольных фрагментов текста в произвольные позиции в текстовом файле. Эта функция является частью большой программы, которую я сейчас пишу.

Читая описание java.util.RandomAccessFile, выясняется, что любые операции записи, выполняемые в середине файла, фактически перезаписывают существующий контент. Это побочный эффект, которого я бы хотел избежать (если это возможно).

Есть ли простой способ добиться этого?

Заранее спасибо.

Ответы [ 7 ]

16 голосов
/ 10 июля 2013

Хорошо, этот вопрос довольно старый, но FileChannels существуют с Java 1.4, и я не знаю, почему они нигде не упоминаются при решении проблемы замены или вставки содержимого в файлы. FileChannels быстрые, используйте их.

Вот пример (игнорирование исключений и некоторых других вещей):

public void insert(String filename, long offset, byte[] content) {
  RandomAccessFile r = new RandomAccessFile(new File(filename), "rw");
  RandomAccessFile rtemp = new RandomAccessFile(new File(filename + "~"), "rw");
  long fileSize = r.length();
  FileChannel sourceChannel = r.getChannel();
  FileChannel targetChannel = rtemp.getChannel();
  sourceChannel.transferTo(offset, (fileSize - offset), targetChannel);
  sourceChannel.truncate(offset);
  r.seek(offset);
  r.write(content);
  long newOffset = r.getFilePointer();
  targetChannel.position(0L);
  sourceChannel.transferFrom(targetChannel, newOffset, (fileSize - offset));
  sourceChannel.close();
  targetChannel.close();
}
11 голосов
/ 14 ноября 2008

Ну, нет, я не верю, что есть способ избежать перезаписи существующего контента с помощью одного стандартного вызова Java IO API.

Если файлы не слишком велики, просто прочитайте весь файл в ArrayList (запись на строку) и либо перезапишите записи, либо вставьте новые записи для новых строк.

Затем перезапишите существующий файл новым содержимым или переместите существующий файл в резервную копию и запишите новый файл.

В зависимости от того, насколько сложными должны быть изменения, может потребоваться изменить структуру данных.

Другим методом будет чтение символов из существующего файла во время записи в отредактированный файл и редактирование потока по мере его чтения.

4 голосов
/ 04 июня 2011

Вы можете использовать следующий код:

BufferedReader reader = null;
BufferedWriter writer = null;
ArrayList list = new ArrayList();

try {
    reader = new BufferedReader(new FileReader(fileName));
    String tmp;
    while ((tmp = reader.readLine()) != null)
        list.add(tmp);
    OUtil.closeReader(reader);

    list.add(0, "Start Text");
    list.add("End Text");

    writer = new BufferedWriter(new FileWriter(fileName));
    for (int i = 0; i < list.size(); i++)
        writer.write(list.get(i) + "\r\n");
} catch (Exception e) {
    e.printStackTrace();
} finally {
    OUtil.closeReader(reader);
    OUtil.closeWriter(writer);
}
4 голосов
/ 21 мая 2009

Если у Java есть способ хранения файлов карты памяти, то вы можете расширить файл до новой длины, отобразить файл, записать все байты до конца, чтобы сделать дыру, и записать новые данные в отверстие.

Это работает на C. Никогда не пробовал на Java.

Другой способ, которым я только что подумал, сделать то же самое, но с произвольным доступом к файлам.

  • Поиск до конца - 1 МБ
  • Чтение 1 МБ
  • Запишите это в исходное положение + размер зазора.
  • Повторите для каждого предыдущего 1 МБ, работающего в направлении начала файла.
  • Остановитесь, когда достигнете желаемой позиции разрыва.

Используйте больший размер буфера для повышения производительности.

2 голосов
/ 14 ноября 2008

Я не знаю, есть ли удобный способ сделать это прямо иначе, чем

  • прочитайте начало файла и запишите его в цель
  • написать новый текст для цели
  • Прочитайте остальную часть файла и запишите его в цель.

О цели: Вы можете создать новое содержимое файла в памяти и затем перезаписать старое содержимое файла, если обрабатываемые файлы не такие большие. Или вы можете записать результат во временный файл.

Эту вещь, вероятно, проще всего сделать с потоками, RandomAccessFile, похоже, не предназначен для вставки в середину (afaik). Проверьте учебник , если вам нужно.

2 голосов
/ 14 ноября 2008

Я считаю, что единственный способ вставить текст в существующий текстовый файл - это прочитать оригинальный файл и записать содержимое во временный файл с добавленным новым текстом. Затем удалите исходный файл и переименуйте временный файл в исходное имя.

Этот пример сфокусирован на вставке одной строки в существующий файл, но все же может пригодиться вам.

0 голосов
/ 23 сентября 2009

Если это текстовый файл ,,,, прочтите существующий файл в StringBuffer и добавьте новое содержимое в тот же StringBuffer, теперь вы можете записать SrtingBuffer в файл. так что теперь файл содержит как существующий, так и новый текст.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...