Insertar texto en un archivo existente a través de Java


Me gustaría crear un programa simple (en Java) que edite archivos de texto, particularmente uno que realice la inserción de fragmentos de texto arbitrarios en posiciones aleatorias en un archivo de texto. Esta característica es parte de un programa más grande que estoy escribiendo actualmente.

Leyendo la descripción sobre java.útil.RandomAccessFile, parece que cualquier operación de escritura realizada en medio de un archivo en realidad sobrescribiría el contenido que sale. Este es un efecto secundario que me gustaría evitar (si posible).

Hay una manera sencilla de lograr esto?

Gracias de antemano.

Author: Benedikt Waldvogel, 2008-11-14

7 answers

Bien, esta pregunta es bastante antigua, pero los FileChannels existen desde Java 1.4 y no se por qué no se mencionan en ninguna parte cuando se trata del problema de reemplazar o insertar contenido en archivos. Los FileChannels son rápidos, úsalos.

Aquí hay un ejemplo (ignorando excepciones y algunas otras cosas):

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();
}
 15
Author: xor_eq,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-07-10 08:35:23

Bueno, no, no creo que haya una manera de evitar sobrescribir el contenido existente con una sola llamada a la API Java IO estándar.

Si los archivos no son demasiado grandes, simplemente lea el archivo completo en una ArrayList (una entrada por línea) y vuelva a escribir entradas o inserte nuevas entradas para nuevas líneas.

Luego sobrescribe el archivo existente con nuevo contenido, o mueve el archivo existente a una copia de seguridad y escribe un nuevo archivo.

Dependiendo de cuán sofisticadas deben ser las ediciones, sus datos la estructura puede necesitar cambiar.

Otro método sería leer caracteres del archivo existente mientras se escribe en el archivo editado y editar la secuencia a medida que se lee.

 11
Author: Ken Gentle,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-11-14 12:57:33

Si Java tiene una forma de mapear archivos de memoria, entonces lo que puede hacer es extender el archivo a su nueva longitud, mapear el archivo, memmove todos los bytes hasta el final para hacer un agujero y escribir los nuevos datos en el agujero.

Esto funciona en C. Nunca lo probé en Java.

Otra forma que acabo de pensar en hacer lo mismo, pero con acceso a archivos aleatorios.

  • Buscar hasta el final-1 MB
  • Debe decir 1 MB
  • Escriba eso en la posición original + tamaño del espacio.
  • Repetir para cada anterior 1 MB trabajando hacia el principio del archivo.
  • Deténgase cuando alcance la posición de separación deseada.

Utilice un tamaño de búfer más grande para un rendimiento más rápido.

 4
Author: Zan Lynx,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-09-24 07:55:54

Puede utilizar el siguiente código:

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
Author: S.Yavari,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-07-16 03:38:23

No se si hay una manera práctica de hacerlo directamente de otra manera que

  • lea el principio del archivo y escríbalo en target
  • escriba su nuevo texto en target
  • lea el resto del archivo y escríbalo en target.

Acerca del destino : Puede construir el nuevo contenido del archivo en memoria y luego sobrescribir el contenido antiguo del archivo si los archivos manejados no son tan grandes. O puede escribir el resultado en un archivo temporal.

La cosa sería probablemente sea más fácil de hacer con secuencias, RandomAccessFile no parece estar destinado a insertarse en el medio (afaik). Revisa el tutorial si lo necesitas.

 2
Author: Touko,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-11-14 12:55:33

Creo que la única manera de insertar texto en un archivo de texto existente es leer el archivo original y escribir el contenido en un archivo temporal con el nuevo texto insertado. A continuación, borre el archivo original y cambie el nombre del archivo temporal al nombre original.

Este ejemplo se centra en insertar una sola línea en un archivo existente, pero aún así tal vez de uso.

 2
Author: Brendan Cashman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-11-14 13:07:00

Si se trata de un archivo de texto,,,,Lea el archivo existente en StringBuffer y añada el nuevo contenido en el mismo StringBuffer ahora u puede escribir el SrtingBuffer en el archivo. así que ahora el archivo contiene tanto el texto existente como el nuevo.

 0
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-09-23 19:08:29