Java: la apertura y la lectura de un archivo sin bloquearlo
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());
}
}
}
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:
- https: // github. com / AugustusKling / rendimiento / blob / master / src / main / java / rendimiento / input / archivo / FileMonitor.java
- El se utiliza anteriormente por https: // github.com/AugustusKling/yield/blob/master/src/main/java/yield/input/file/FileInput.java para crear una operación de cola. El
queue.feed(lineContent)
pasa contenido línea para el procesamiento por los oyentes y sería igual a suthis.parse(…)
.
examineFile(…)
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
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