2009-05-04 204 views
26

Tengo un archivo de texto que quiero editar usando Java. Tiene muchos miles de líneas. Básicamente, quiero repetir las líneas y cambiar/editar/eliminar algún texto. Esto tendrá que suceder con bastante frecuencia.Modificar un archivo .txt en Java

partir de las soluciones que he visto en otros sitios, el enfoque general parece ser:

  • Abrir el archivo existente utilizando un BufferedReader
  • Lea cada línea, realizar modificaciones en cada línea, y añadirlo a un StringBuilder
  • una vez que todo el texto ha sido leído y modificado, escribir el contenido de la StringBuilder en un nuevo archivo
  • Reemplazar el archivo antiguo con el nuevo archivo

Esta solución me parece un poco "hacky", especialmente si tengo miles de líneas en mi archivo de texto.

¿Alguien sabe de una solución mejor?

+0

Puede usar RandomAccessFile en Java para modificar el archivo sin volver a escribir todo el archivo. Vea la información detallada a continuación publicada por mí. – sendon1982

Respuesta

29

No he hecho esto recientemente en Java, pero escribir un archivo completo en la memoria parece una mala idea.

La mejor idea que se me ocurre es abrir un archivo temporal en modo de escritura al mismo tiempo, y para cada línea, leerlo, modificarlo si es necesario, luego escribir en el archivo temporal. Al final, elimine el original y cambie el nombre del archivo temporal.

Si tiene permisos de modificación en el sistema de archivos, probablemente también tenga permisos de eliminación y cambio de nombre.

+1

Resulta que mi respuesta fue incorrecta; Olvidé que RandomAccessFile no permite las inserciones o eliminaciones. Creo que esta es la mejor respuesta. –

+0

Terminé usando este enfoque con un BufferedReader y BufferedWriter. –

2

Si el archivo es grande, es posible que desee utilizar un FileStream como salida, pero parece más o menos el proceso más simple para hacer lo que está pidiendo (y sin más especificidad, es decir, qué tipos de cambios/modificaciones/eliminaciones que está tratando de hacer, es imposible determinar qué manera más complicada podría funcionar).

1

En general, no puede editar el archivo en su lugar; es simplemente una secuencia muy larga de caracteres, que pasa a incluir caracteres de nueva línea. Puede editar en su lugar si sus cambios no cambian la cantidad de caracteres en cada línea.

2

No hay razón para almacenar en búfer todo el archivo.

Simplemente escriba cada línea como la leyó, inserte líneas cuando sea necesario, elimine las líneas cuando sea necesario, reemplace las líneas cuando sea necesario.

Fundamentalmente, no tendrá que volver a tener que volver a crear el archivo al por mayor, especialmente si se trata simplemente de un archivo de texto.

2

¿Qué tipo de datos es? ¿Controlas el formato del archivo?

Si el archivo contiene pares de nombre/valor (o similar), puede tener un poco de suerte con Properties, o tal vez improvisar algo con un controlador de archivo plano JDBC.

Como alternativa, ¿ha considerado no escribir los datos con tanta frecuencia? Operar en una copia en la memoria de su archivo debería ser relativamente trivial. Si no hay recursos externos que necesiten actualizaciones en tiempo real del archivo, entonces no hay necesidad de ir al disco cada vez que quiera hacer una modificación. Puede ejecutar una tarea programada para escribir actualizaciones periódicas en el disco si le preocupa la copia de seguridad de datos.

5

si el archivo tiene solo unos pocos miles de líneas, debería poder leer todo el archivo en una sola lectura y convertirlo en una Cadena.

Puede usar apache IOUtils que tiene un método como el siguiente.

public static String readFile(String filename) throws IOException { 
    File file = new File(filename); 
    int len = (int) file.length(); 
    byte[] bytes = new byte[len]; 
    FileInputStream fis = null; 
    try { 
     fis = new FileInputStream(file); 
     assert len == fis.read(bytes); 
    } catch (IOException e) { 
     close(fis); 
     throw e; 
    } 
    return new String(bytes, "UTF-8"); 
} 

public static void writeFile(String filename, String text) throws IOException { 
    FileOutputStream fos = null; 
    try { 
     fos = new FileOutputStream(filename); 
     fos.write(text.getBytes("UTF-8")); 
    } catch (IOException e) { 
     close(fos); 
     throw e; 
    } 
} 

public static void close(Closeable closeable) { 
    try { 
     closeable.close(); 
    } catch(IOException ignored) { 
    } 
} 
1

¿No puedes usar expresiones regulares, si sabes lo que quieres cambiar? Jakarta Regexp probablemente debería hacer el truco.

1

Aunque esta pregunta hace un tiempo ha escrito, creo que es bueno para poner mi respuesta aquí. Creo que el mejor enfoque es usar FileChannel del paquete java.nio.channels en este escenario. ¡Pero esto, solo si necesita tener un buen rendimiento! Usted tendría que obtener una FileChannel a través de un RandomAccessFile, así:

java.nio.channels.FileChannel channel = new java.io.RandomAccessFile("/my/fyle/path", "rw").getChannel();

Después de esto, se necesita una para crear un ByteBuffer donde se leerá desde el FileChannel.

esto parece algo como esto:


java.nio.ByteBuffer inBuffer = java.nio.ByteBuffer.allocate(100); 
int pos = 0; 
int aux = 0; 
StringBuilder sb = new StringBuilder(); 

while (pos != -1) { 

    aux = channel.read(inBuffer, pos); 
    pos = (aux != -1) ? pos + aux : -1; 

    b = inBuffer.array(); 
    sb.delete(0, sb.length()); 

    for (int i = 0; i < b.length; ++i) { 

     sb.append((char)b[i]); 

    } 

    //here you can do your stuff on sb 

    inBuffer = ByteBuffer.allocate(100); 

} 

la esperanza de que mi respuesta le ayudará!

1

Puede usar RandomAccessFile en Java para modificar el archivo con una condición: El tamaño de cada línea debe ser reparado; de lo contrario, cuando se vuelva a escribir una nueva cadena, podría anularla en la siguiente línea.

Por lo tanto, en mi ejemplo, configuré la longitud de línea como 100 y relleno con cadena de espacio al crear el archivo y escribir de nuevo en el archivo.

Para permitir la actualización, necesita establecer la longitud de la línea un poco más grande que la longitud más larga de la línea en este archivo.

public class RandomAccessFileUtil { 
public static final long RECORD_LENGTH = 100; 
public static final String EMPTY_STRING = " "; 
public static final String CRLF = "\n"; 

public static final String PATHNAME = "/home/mjiang/JM/mahtew.txt"; 

/** 
* one two three 
    Text to be appended with 
    five six seven 
    eight nine ten 
* 
* 
* @param args 
* @throws IOException 
*/ 
public static void main(String[] args) throws IOException 
{ 
    String starPrefix = "Text to be appended with"; 
    String replacedString = "new text has been appended"; 

    RandomAccessFile file = new RandomAccessFile(new File(PATHNAME), "rw"); 

    String line = ""; 
    while((line = file.readLine()) != null) 
    { 
     if(line.startsWith(starPrefix)) 
     { 
      file.seek(file.getFilePointer() - RECORD_LENGTH - 1); 
      file.writeBytes(replacedString); 
     } 

    } 
} 

public static void createFile() throws IOException 
{ 
    RandomAccessFile file = new RandomAccessFile(new File(PATHNAME), "rw"); 

    String line1 = "one two three"; 
    String line2 = "Text to be appended with"; 
    String line3 = "five six seven"; 
    String line4 = "eight nine ten"; 

    file.writeBytes(paddingRight(line1)); 
    file.writeBytes(CRLF); 
    file.writeBytes(paddingRight(line2)); 
    file.writeBytes(CRLF); 
    file.writeBytes(paddingRight(line3)); 
    file.writeBytes(CRLF); 
    file.writeBytes(paddingRight(line4)); 
    file.writeBytes(CRLF); 

    file.close(); 

    System.out.println(String.format("File is created in [%s]", PATHNAME)); 
} 

public static String paddingRight(String source) 
{ 
    StringBuilder result = new StringBuilder(100); 
    if(source != null) 
    { 
     result.append(source); 
     for (int i = 0; i < RECORD_LENGTH - source.length(); i++) 
     { 
      result.append(EMPTY_STRING); 
     } 
    } 

    return result.toString(); 
} 

}

0

Puede cambiar el archivo txt a java por el ahorro en hacer clic en "Guardar como" y guardar * .java extensión.

Cuestiones relacionadas