Eu tenho um aplicativo que grava informações em um arquivo. Essas informações são usadas pós-execução para determinar a aprovação / falha / correção do aplicativo. Eu gostaria de poder ler o arquivo enquanto ele está sendo escrito para que eu possa fazer essas verificações de aprovação / falha / exatidão em tempo real.
Presumo que seja possível fazer isso, mas quais são as pegadinhas envolvidas ao usar Java? Se a leitura alcançar a gravação, ela apenas aguardará por mais gravações até que o arquivo seja fechado ou a leitura lançará uma exceção neste ponto? Se for o último, o que eu faço então?
Minha intuição está atualmente me empurrando para BufferedStreams. É este o caminho a percorrer?
Respostas:
Não foi possível fazer o exemplo funcionar
FileChannel.read(ByteBuffer)
porque não é uma leitura de bloqueio. No entanto, conseguiu que o código abaixo funcionasse:Claro que a mesma coisa funcionaria como um temporizador em vez de um thread, mas deixo isso para o programador. Ainda estou procurando uma maneira melhor, mas isso funciona para mim por enquanto.
Ah, e vou advertir isso com: Estou usando 1.4.2. Sim, eu sei que ainda estou na idade da pedra.
fonte
Se você deseja ler um arquivo enquanto ele está sendo escrito e apenas ler o novo conteúdo, o seguinte o ajudará a conseguir o mesmo.
Para executar este programa, você irá iniciá-lo a partir do prompt de comando / janela do terminal e passar o nome do arquivo para leitura. Ele lerá o arquivo, a menos que você mate o programa.
java FileReader c: \ myfile.txt
Conforme você digita uma linha de texto, salve-a do bloco de notas e você verá o texto impresso no console.
fonte
BufferedReader
criação em cada chamada de loop é tão inútil. Com ele sendo criado uma vez, o salto não seria necessário, pois o leitor em buffer leria as novas linhas à medida que chegassem.Você também pode dar uma olhada no canal java para bloquear uma parte de um arquivo.
http://java.sun.com/javase/6/docs/api/java/nio/channels/FileChannel.html
Esta função do
FileChannel
pode ser um começoUma invocação deste método irá bloquear até que a região possa ser bloqueada
fonte
Eu concordo totalmente com a resposta de Joshua , Tailer está apto para o trabalho nesta situação. Aqui está um exemplo :
Ele grava uma linha a cada 150 ms em um arquivo, enquanto lê esse mesmo arquivo a cada 2500 ms
fonte
A resposta parece ser "não" ... e "sim". Parece não haver uma maneira real de saber se um arquivo está aberto para gravação por outro aplicativo. Portanto, a leitura desse arquivo irá apenas progredir até que o conteúdo se esgote. Segui o conselho de Mike e escrevi alguns códigos de teste:
Writer.java grava uma string no arquivo e, em seguida, espera que o usuário pressione Enter antes de gravar outra linha no arquivo. A ideia é que ele possa ser iniciado, então um leitor pode ser iniciado para ver como ele lida com o arquivo "parcial". O leitor que escrevi está em Reader.java.
Writer.java
Reader.java
Não há garantias de que este código seja a prática recomendada.
Isso deixa a opção sugerida por Mike de verificar periodicamente se há novos dados a serem lidos do arquivo. Isso exige a intervenção do usuário para fechar o leitor de arquivos quando for determinado que a leitura foi concluída. Ou, o leitor precisa estar ciente do conteúdo do arquivo e ser capaz de determinar a condição de fim de gravação. Se o conteúdo fosse XML, o final do documento poderia ser usado para sinalizar isso.
fonte
Não é o Java em si, mas você pode encontrar problemas em que escreveu algo em um arquivo, mas ainda não foi realmente escrito - pode estar em um cache em algum lugar, e a leitura do mesmo arquivo pode não fornecer as novas informações.
Versão curta - use flush () ou qualquer outra chamada de sistema relevante para garantir que seus dados sejam realmente gravados no arquivo.
Nota Eu não estou falando sobre o cache de disco no nível do sistema operacional - se seus dados entrarem aqui, eles deverão aparecer em um read () após este ponto. Pode ser que a própria linguagem armazene em cache as gravações, esperando até que um buffer seja preenchido ou que o arquivo seja liberado / fechado.
fonte
Há um Java Graphic Tail de código aberto que faz isso.
https://stackoverflow.com/a/559146/1255493
fonte
Você não pode ler um arquivo aberto a partir de outro processo usando FileInputStream, FileReader ou RandomAccessFile.
Mas usar FileChannel diretamente funcionará:
fonte
Nunca tentei fazer isso, mas você deve escrever um caso de teste para ver se a leitura de um fluxo depois de chegar ao fim funcionará, independentemente de haver mais dados gravados no arquivo.
Existe um motivo pelo qual você não pode usar um fluxo de entrada / saída canalizado? Os dados estão sendo gravados e lidos no mesmo aplicativo (se sim, você possui os dados, por que precisa ler o arquivo)?
Caso contrário, talvez leia até o final do arquivo, então monitore as mudanças e busque de onde você parou e continue ... embora esteja atento às condições de corrida.
fonte