Pergunta

Eu preciso ser capaz de imitar a 'cauda' com Java. Estou tentando ler um arquivo de log como está sendo escrito por outro processo, mas quando abro o arquivo para lê -lo, ele bloqueia o arquivo e o outro processo não pode mais gravar nele. Qualquer ajuda seria muito apreciada!

Aqui está o código que estou usando atualmente:

public void read(){
    Scanner fp = null;
    try{
        fp = new Scanner(new FileReader(this.filename));
        fp.useDelimiter("\n");
    }catch(java.io.FileNotFoundException e){
        System.out.println("java.io.FileNotFoundException e");
    }
    while(true){
        if(fp.hasNext()){
            this.parse(fp.next());
        }           
    }       
}
Foi útil?

Solução

A cauda de reconstrução é complicada devido a alguns casos especiais, como truncamento de arquivos e exclusão (intermediária). Para abrir o arquivo sem travar o uso StandardOpenOption.READ com a nova API de arquivo java como assim:

try (InputStream is = Files.newInputStream(path, StandardOpenOption.READ)) {
    InputStreamReader reader = new InputStreamReader(is, fileEncoding);
    BufferedReader lineReader = new BufferedReader(reader);
    // Process all lines.
    String line;
    while ((line = lineReader.readLine()) != null) {
        // Line content content is in variable line.
    }
}

Para minha tentativa de criar uma cauda em Java, consulte:

Sinta -se à vontade para inspirar -se nesse código ou simplesmente copiar as peças necessárias. Deixe -me saber se você encontrar algum problema que eu não esteja ciente.

Outras dicas

Veja a API do FileChannel aqui. Para travar o arquivo que você pode verificar aqui

java.io fornece um bloqueio de arquivo obrigatório e java.nio oferece um bloqueio de arquivo consultivo

Se você quiser ler qualquer arquivo sem bloqueio, você pode usar abaixo as aulas

import java.nio.channels.FileChannel;
import java.nio.file.Paths;

Se você deseja atingir uma linha de arquivo por linha, use abaixo o código para o mesmo

public void tail(String logPath){
    String logStr = null;
    FileChannel fc = null;
    try {
        fc = FileChannel.open(Paths.get(logPath), StandardOpenOption.READ);
        fc.position(fc.size());
    } catch (FileNotFoundException e1) {
        System.out.println("FileNotFoundException occurred in Thread : " + Thread.currentThread().getName());
        return;
    } catch (IOException e) {
        System.out.println("IOException occurred while opening FileChannel in Thread : " + Thread.currentThread().getName());
    }
    while (true) {
        try {
            logStr = readLine(fc);
            if (logStr != null) {
                System.out.println(logStr);
            } else {
                Thread.sleep(1000);
            }
        } catch (IOException|InterruptedException e) {
            System.out.println("Exception occurred in Thread : " + Thread.currentThread().getName());
            try {
                fc.close();
            } catch (IOException e1) {
            }
            break;
        }
    }
}

private String readLine(FileChannel fc) throws IOException {
    ByteBuffer buffers = ByteBuffer.allocate(128);
    // Standard size of a line assumed to be 128 bytes
    long lastPos = fc.position();
    if (fc.read(buffers) > 0) {
        byte[] data = buffers.array();
        boolean foundTmpTerminator = false;
        boolean foundTerminator = false;
        long endPosition = 0;
        for (byte nextByte : data) {
            endPosition++;
            switch (nextByte) {
            case -1:
                foundTerminator = true;
                break;
            case (byte) '\r':
                foundTmpTerminator = true;
                break;
            case (byte) '\n':
                foundTmpTerminator = true;
                break;
            default:
                if (foundTmpTerminator) {
                    endPosition--;
                    foundTerminator = true;
                }
            }
            if (foundTerminator) {
                break;
            }
        }
        fc.position(lastPos + endPosition);
        if (foundTerminator) {
            return new String(data, 0, (int) endPosition);
        } else {
            return new String(data, 0, (int) endPosition) + readLine(fc);
        }
    }
    return null;
}

O Windows usa bloqueio obrigatório para arquivos, a menos que você especifique os sinalizadores de compartilhamento certos enquanto você abre. Se você deseja abrir um arquivo ocupado, precisa Win32-api CreateFile uma alça com as bandeiras de compartilhamento FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE.

Isso é usado dentro do JDK em alguns lugares para abrir arquivos para leitura de atributos e outras coisas, mas até onde eu posso ver que não está exportado/disponível para o nível da biblioteca de classes Java. Então você precisaria encontrar uma biblioteca nativa para fazer isso.

Eu acho que como um trabalho rápido ao seu redor pode ler process.getInputStream() do comando "cmd /D/C type file.lck"

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top