Domanda

Ho bisogno di essere in grado di imitare 'tail -f' con Java. Sto cercando di leggere un file di log, come è stato scritto da un altro processo, ma quando ho aperto il file per leggerlo, questo blocca il file e l'altro processo non può scrivere più. Qualsiasi aiuto sarebbe molto apprezzato!

Ecco il codice che sto usando attualmente:

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());
        }           
    }       
}
È stato utile?

Soluzione

La ricostruzione di coda è difficile a causa di alcuni casi particolari, come il troncamento di file e la cancellazione (intermedio). Per aprire il file senza bloccare l'uso StandardOpenOption.READ con la nuova API file di Java in questo modo:

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

Per il mio tentativo di creare una coda in Java si veda:

Non esitate a prendere spunto da quel codice o semplicemente copiare le parti che richiedono. Fatemi sapere se trovate tutti i problemi che io non sono a conoscenza.

Altri suggerimenti

Guarda l'API FileChannel qui . Per bloccare il file è possibile controllare qui

  

java.io ti dà un blocco di file obbligatoria e java.nio ti dà un   blocco di file advisory

Se si vuole leggere qualsiasi file senza alcuna serratura è possibile utilizzare sotto classi

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

Se si vuole coda un file riga per riga sotto l'uso di codice per lo stesso

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 utilizza il blocco obbligatorio per i file se non si specifica il diritto bandiere di condivisione, mentre si apre. Se si desidera aprire un file occupato, è necessario Win32 API CreateFile una maniglia con la condivisione bandiere FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE.

Questo è utilizzato all'interno del JDK in pochi luoghi per aprire i file per la lettura di attributi e le cose, ma per quanto posso vedere, non viene esportato / disponibili al livello del Java Class Library. Così si avrebbe bisogno di trovare una libreria nativa per farlo.

Credo che come un rapido lavoro intorno si può leggere process.getInputStream() dal comando "cmd /D/C type file.lck"

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top