2008-11-14 17 views
23

Me gustaría crear un programa simple (en Java) que edite archivos de texto, particularmente uno que realiza 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.Insertar texto en un archivo existente mediante Java

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

¿Hay una manera simple de lograr esto?

Gracias de antemano.

+4

Para que lo entienda, esto no es sólo una limitación en Java. Esto es más o menos cómo funciona todo I/O. Es la funcionalidad que proporciona el sistema operativo subyacente. –

+3

Quizás haya una implementación del sistema de archivos que admita algo así como bloques de datos de listas vinculadas que probablemente podrían permitir la inserción rápida de datos en el medio de un archivo. Sin embargo, uno necesitaría llamadas al sistema de bajo nivel para lograrlo. –

+1

No puedo encontrar el artículo exacto, pero leí uno que explica cómo usar una cuerda como la estructura de datos que maneja un editor de texto simple. http://en.wikipedia.org/wiki/Rope_%28computer_science%29 – Albert

Respuesta

15

bien, esta pregunta es bastante viejo, pero existe FileChannels desde Java 1.4 y no sé por qué no se menciona en ninguna parte cuando se trata con el problema de la reemplazando o insertando contenido en archivos. FileChannels son rápidos, úselos.

He aquí un ejemplo (haciendo caso omiso de las 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(); 
} 
+0

¿Puedo usar FileChannel para superponer texto en la imagen? – NPE

+0

En general, puede usar FileChannels para modificar cualquier tipo de archivos como desee. Sin embargo, la cosa es: para todos los casos de uso que pueda imaginar, debe saber qué escribir en el archivo. Si su imagen es un .SVG, podría, por supuesto, usar un FileChannel para escribir el elemento xml necesario en el archivo. Pero como su pregunta no era tan específica, la respuesta es: "No, porque no sabe lo que está haciendo". . Podrías echarle un vistazo a las clases java.awt.Image y especialmente a la clase BufferedImage y leer de manera legible un tutorial al respecto y comenzar desde allí. –

+0

Sí, después de hacer algunas investigaciones. Yo uso el objeto 'Graphic' en lugar de FileChannel. – NPE

2

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 por el nombre original.

Este example se enfoca en insertar una sola línea en un archivo existente, pero igual puede ser útil para usted.

2

No sé si hay una manera práctica de hacerlo directamente de otro modo que

  • leer el principio del archivo y la escribo para apuntar
  • escribir el texto nuevo para apuntar
  • lectura el resto del archivo y escríbalo en el destino.

Sobre el objetivo: Puede construir los nuevos contenidos del archivo en la memoria y luego sobrescribir el contenido anterior del archivo si los archivos manejados no son tan grandes. O puede escribir el resultado en un archivo temporal.

Lo que probablemente sea más fácil de hacer con las transmisiones, RandomAccessFile no parece estar destinado a insertarse en el medio (afaik). Compruebe el tutorial si lo necesita.

11

Bueno, no, no creo que exista una forma de evitar sobrescribir el contenido existente con una sola invocación de la API IO de Java estándar.

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

Luego, sobrescriba el archivo existente con contenido nuevo o mueva el archivo existente a una copia de seguridad y escriba un nuevo archivo.

Dependiendo de qué tan sofisticadas deben ser las ediciones, es posible que su estructura de datos deba cambiar.

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

3

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

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

Otra forma en la que pensé hacer lo mismo pero con acceso aleatorio a archivos.

  • Se desplaza hasta el final - 1 MB
  • Leer 1 MB
  • escribir que a su posición original + tamaño de la separación.
  • Repita para cada 1 MB anterior trabajando hacia el principio del archivo.
  • Deténgalo cuando llegue a la posición de espacio deseado.

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

0

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

4

Puede utilizar 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); 
} 
Cuestiones relacionadas