Modifique um arquivo .txt em Java

Eu tenho um arquivo de texto que eu quero editar usando o Java. Tem muitos milhares de linhas. Eu basicamente quero iterar através das linhas e alterar / editar / excluir algum texto. Isso precisará acontecer com bastante frequência.

Das soluções que vi em outros sites, a abordagem geral parece ser:

  • Abra o arquivo existente usando um BufferedReader
  • Leia cada linha, faça modificações em cada linha e adicione-a a um StringBuilder
  • Depois que todo o texto tiver sido lido e modificado, grave o conteúdo do StringBuilder em um novo arquivo
  • Substitua o arquivo antigo pelo novo arquivo

Esta solução parece um pouco “hacky” para mim, especialmente se eu tiver milhares de linhas no meu arquivo de texto.

Alguém sabe de uma solução melhor?

Eu não fiz isso em Java recentemente, mas escrever um arquivo inteiro na memory parece ser uma má ideia.

A melhor idéia que posso criar é abrir um arquivo temporário no modo de escrita ao mesmo tempo e, para cada linha, ler, modificar, se necessário, e gravar no arquivo temporário. No final, exclua o original e renomeie o arquivo temporário.

Se você tiver permissions de modificação no sistema de arquivos, provavelmente também terá a exclusão e a renomeação de permissions.

se o arquivo tiver apenas alguns milhares de linhas, você poderá ler o arquivo inteiro em uma leitura e convertê-lo em uma String.

Você pode usar o IOUtils do apache, que tem o seguinte método.

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) { } } 

Se o arquivo é grande, você pode querer usar um FileStream para a saída, mas parece que é o processo mais simples de fazer o que você está perguntando (e sem mais especificidade, ou seja, quais tipos de mudanças / edições / exclusões você está tentando fazer, é impossível determinar qual caminho mais complicado pode funcionar).

Nenhuma razão para armazenar todo o arquivo.

Simplesmente escreva cada linha como a lê, insira linhas quando necessário, apague as linhas quando necessário, substitua as linhas quando necessário.

Fundamentalmente, você não vai ter que recriar o arquivo atacado, especialmente se for apenas um arquivo de texto.

Que tipo de dados são? Você controla o formato do arquivo?

Se o arquivo contiver pares nome / valor (ou similar), você poderá ter alguma sorte com as Propriedades ou talvez remendar algo usando um driver JDBC de arquivo simples.

Como alternativa, você considerou não gravar os dados com tanta frequência? Operar em uma cópia na memory do seu arquivo deve ser relativamente trivial. Se não houver resources externos que precisem de atualizações em tempo real do arquivo, não há necessidade de ir ao disco toda vez que você quiser fazer uma modificação. Você pode executar uma tarefa agendada para gravar atualizações periódicas no disco se estiver preocupado com o backup de dados.

Em geral, você não pode editar o arquivo no lugar; é simplesmente uma seqüência muito longa de caracteres, que inclui caracteres de nova linha. Você poderia editar no local se suas alterações não alterassem o número de caracteres em cada linha.

Você não pode usar expressões regulares, se você sabe o que você quer mudar? Jakarta Regexp provavelmente deve fazer o truque.

Embora essa pergunta tenha sido postada há algum tempo, acho que é bom colocar minha resposta aqui. Eu acho que a melhor abordagem é usar o FileChannel do pacote java.nio.channels nesse cenário. Mas isso, só se você precisa ter um bom desempenho! Você precisaria obter um FileChannel via RandomAccessFile , assim:

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

Depois disso, você precisa criar um ByteBuffer onde irá ler o FileChannel .

isso é algo como isto:

 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); } 

Espero que minha resposta te ajude!

Eu acho que, FileOutputStream.getFileChannel() vai ajudar muito, veja api FileChannel http://java.sun.com/javase/6/docs/api/java/nio/channels/FileChannel.html

Você pode usar RandomAccessFile em Java para modificar o arquivo com uma condição: o tamanho de cada linha deve ser corrigido; caso contrário, quando uma nova string for gravada, ela poderá replace a string na próxima linha.

Portanto, no meu exemplo, defino o comprimento da linha como 100 e preenchimento com a string space ao criar o arquivo e gravar de volta no arquivo.

Portanto, para permitir a atualização, você precisa definir o comprimento da linha um pouco maior que o comprimento mais longo da linha nesse arquivo.

 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(); } 

}

Você pode alterar o arquivo txt para java salvando clicando em “Salvar como” e salvando a extensão * .java.