Question

Je dois être capable d'imiter « tail -f » avec Java. Je suis en train de lire un fichier journal comme il est écrit par un autre processus, mais quand j'ouvre le fichier pour le lire, il verrouille le fichier et l'autre processus ne peut pas écrire plus. Toute aide serait grandement appréciée!

Voici le code que je suis actuellement en utilisant:

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());
        }           
    }       
}
Était-ce utile?

La solution

La reconstruction de queue est difficile en raison de certains cas particuliers tels que la troncature de fichier et la suppression (intermédiaire). Pour ouvrir le fichier sans bloquer l'utilisation StandardOpenOption.READ avec la nouvelle API de fichiers Java comme ceci:

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

Pour ma tentative de créer une queue en Java voir:

Ne hésitez pas à nous inspirer de ce code ou copier simplement les pièces dont vous avez besoin. Faites-moi savoir si vous trouvez des questions que je ne suis pas au courant.

Autres conseils

Regardez l'API FileChannel . Pour verrouiller le fichier que vous pouvez vérifier ici

  

java.io vous donne un verrou de fichier obligatoire et java.nio vous donne une   verrouillage du fichier consultatif

Si vous voulez lire un fichier sans vous verrouillez pouvez utiliser les classes ci-dessous

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

Si vous voulez la queue une ligne de fichier par l'utilisation de la ligne ci-dessous le code pour le même

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 utilise le verrouillage obligatoire pour les fichiers, sauf si vous spécifiez les drapeaux d'actions à droite pendant que vous ouvrez. Si vous voulez ouvrir un fichier occupé, vous devez Win32 API CreateFile une poignée avec les drapeaux de partage FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE.

Il est utilisé à l'intérieur du JDK dans quelques endroits pour ouvrir des fichiers pour la lecture des attributs et des choses, mais pour autant que je peux le voir est pas exporté / disponible pour la classe Java niveau de la bibliothèque. Donc, vous devez trouver une bibliothèque native de le faire.

Je pense qu'en tant que travail rapide autour de vous pouvez lire process.getInputStream() de la commande "cmd /D/C type file.lck"

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top