Pregunta

Me tienen que ser capaces de imitar 'tail-f' con Java. Estoy intentando leer un archivo de registro, ya que está siendo escrito por otro proceso, pero al abrir el archivo para leerlo, se bloquea el archivo y el otro proceso no puede escribir en él nunca más. Cualquier ayuda sería muy apreciada!

Este es el código que estoy usando actualmente:

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());
        }           
    }       
}
¿Fue útil?

Solución

La reconstrucción de la cola es complicado debido a algunos casos especiales como el truncamiento del archivo y eliminación (intermedio). Para abrir el archivo sin bloquear el uso StandardOpenOption.READ con el nuevo archivo Java API de esta manera:

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.
    }
}

En mi intento de crear una cola en Java ver:

No dude en tomar la inspiración de ese código o simplemente copiar las partes que se requieren. Déjeme saber si usted encuentra cualquier problema que yo no sepa.

Otros consejos

Mire la FileChannel API aquí . Para bloquear el archivo se puede comprobar aquí

  

java.io le da un bloqueo de archivo obligatorios y java.nio le da una   bloqueo de archivo de asesoramiento

Si desea leer cualquier archivo sin ningún tipo de bloqueo se puede utilizar a continuación las clases

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

Si desea cola de un archivo línea por línea de uso por debajo de código para el mismo

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

Windows utiliza un bloqueo obligatorio para los archivos a menos que especifique los indicadores compartidos derecha mientras abre. Si desea abrir un archivo ocupado, es necesario CreateFile Win32 API de un mango con el FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE banderas de intercambio.

Esto se utiliza dentro del JDK en unos pocos lugares a los archivos abiertos para la lectura de atributos y esas cosas, pero por lo que puedo ver que no se exporta / disponibles a nivel de la biblioteca de clases de Java. Por lo que tendría que encontrar una biblioteca nativa de hacer eso.

Creo que como un trabajo rápido alrededor, se puede leer desde el process.getInputStream() "cmd /D/C type file.lck" comando

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top