Java: ouverture et lecture d'un fichier sans le bloquer
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());
}
}
}
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:
- Méthode
examineFile(…)
https: // GitHub. com / AugustusKling / rendement / blob / maître / src / main / java / rendement / entrée / fichier / FileMonitor.java - Ce qui précède est utilisé par https: // github.com/AugustusKling/yield/blob/master/src/main/java/yield/input/file/FileInput.java pour créer une opération de queue. Le
queue.feed(lineContent)
passe contenu en ligne pour le traitement par les auditeurs et égale à votrethis.parse(…)
.
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"