Quiero leer el archivo continuamente como cola GNU con "-f" param. Lo necesito para vivir-leer el archivo de registro. ¿Cuál es la forma correcta de hacerlo?C# leer continuamente el archivo
Respuesta
que desea abrir un FileStream
en modo binario. Periódicamente, busque el final del archivo menos 1024 bytes (o lo que sea), luego lea hasta el final y la salida. Así es como funciona el tail -f
.
Las respuestas a sus preguntas:
binario porque es difícil acceder al azar el archivo si estás leyendo como texto. Tienes que hacer la conversión de binario a texto, pero no es difícil. (Consulte a continuación)
1024 bytes porque es un buen número conveniente, y debe manejar 10 o 15 líneas de texto. Generalmente.
He aquí un ejemplo de abrir el archivo, la lectura de los últimos 1024 bytes, y su conversión a texto:
static void ReadTail(string filename)
{
using (FileStream fs = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
// Seek 1024 bytes from the end of the file
fs.Seek(-1024, SeekOrigin.End);
// read 1024 bytes
byte[] bytes = new byte[1024];
fs.Read(bytes, 0, 1024);
// Convert bytes to string
string s = Encoding.Default.GetString(bytes);
// or string s = Encoding.UTF8.GetString(bytes);
// and output to console
Console.WriteLine(s);
}
}
Tenga en cuenta que debe abrir con FileShare.ReadWrite
, ya que usted está tratando de leer un archivo que está actualmente abierto para escribir por otro proceso.
También tenga en cuenta que utilicé Encoding.Default
, que en inglés/EE. UU. Y para la mayoría de los idiomas de Europa occidental será una codificación de caracteres de 8 bits. Si el archivo está escrito en alguna otra codificación (como UTF-8 u otra codificación Unicode), es posible que los bytes no se conviertan correctamente en caracteres. Tendrás que manejar eso determinando la codificación si crees que esto será un problema. Buscar desbordamiento de pila para obtener información sobre cómo determinar la codificación de texto de un archivo.
Si desea hacer esto periódicamente (cada 15 segundos, por ejemplo), puede configurar un temporizador que llame al método ReadTail
tantas veces como desee. Puede optimizar un poco las cosas abriendo el archivo una sola vez al inicio del programa. Eso depende de usted. enfoque natural
Puede usar la clase FileSystemWatcher que puede enviar notificaciones de diferentes eventos que suceden en el sistema de archivos como el archivo modificado.
OK. Digamos que recibí un evento que el archivo cambió. ¿Cómo puedo leer hasta el final desde la posición que terminé de leer la última vez? Ejemplo de Eny apreciado :) –
Si sólo están buscando una herramienta para hacer esto, entonces echa un vistazo a la versión libre de Bare tail
No, no estoy buscando una herramienta. Necesito una forma de implementarlo en C# para mi programa. –
private void button1_Click(object sender, EventArgs e)
{
if (folderBrowserDialog.ShowDialog() == DialogResult.OK)
{
path = folderBrowserDialog.SelectedPath;
fileSystemWatcher.Path = path;
string[] str = Directory.GetFiles(path);
string line;
fs = new FileStream(str[0], FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
tr = new StreamReader(fs);
while ((line = tr.ReadLine()) != null)
{
listBox.Items.Add(line);
}
}
}
private void fileSystemWatcher_Changed(object sender, FileSystemEventArgs e)
{
string line;
line = tr.ReadLine();
listBox.Items.Add(line);
}
Más de utilizar FileSystemWatcher
:
var wh = new AutoResetEvent(false);
var fsw = new FileSystemWatcher(".");
fsw.Filter = "file-to-read";
fsw.EnableRaisingEvents = true;
fsw.Changed += (s,e) => wh.Set();
var fs = new FileStream("file-to-read", FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
using (var sr = new StreamReader(fs))
{
var s = "";
while (true)
{
s = sr.ReadLine();
if (s != null)
Console.WriteLine(s);
else
wh.WaitOne(1000);
}
}
wh.Close();
Aquí el ciclo de lectura principal se detiene para esperar los datos entrantes y FileSystemWatcher
se utiliza sólo para despertar el ciclo de lectura principal.
Para monitorear continuamente la cola del archivo, solo necesita recordar la longitud del archivo antes.
public static void MonitorTailOfFile(string filePath)
{
var initialFileSize = new FileInfo(filePath).Length;
var lastReadLength = initialFileSize - 1024;
if (lastReadLength < 0) lastReadLength = 0;
while (true)
{
try
{
var fileSize = new FileInfo(filePath).Length;
if (fileSize > lastReadLength)
{
using (var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
fs.Seek(lastReadLength, SeekOrigin.Begin);
var buffer = new byte[1024];
while (true)
{
var bytesRead = fs.Read(buffer, 0, buffer.Length);
lastReadLength += bytesRead;
if (bytesRead == 0)
break;
var text = ASCIIEncoding.ASCII.GetString(buffer, 0, bytesRead);
Console.Write(text);
}
}
}
}
catch { }
Thread.Sleep(1000);
}
}
tuve que usar ASCIIEncoding, ya que este código no es lo suficientemente inteligente como para atender a longitudes de caracteres variables de UTF8 en los límites de amortiguamiento.
Nota: Puede cambiar la parte Thread.Sleep para que tenga diferentes tiempos, y también puede vincularla con un vigilante de archivos y patrón de bloqueo - Monitor.Enter/Wait/Pulse. Para mí, el temporizador es suficiente, y como máximo solo verifica la longitud del archivo cada segundo, si el archivo no ha cambiado.
Esta es mi solución
static IEnumerable<string> TailFrom(string file)
{
using (var reader = File.OpenText(file))
{
while (true)
{
string line = reader.ReadLine();
if (reader.BaseStream.Length < reader.BaseStream.Position)
reader.BaseStream.Seek(0, SeekOrigin.Begin);
if (line != null) yield return line;
else Thread.Sleep(500);
}
}
}
así, en su código que puede hacer
foreach (string line in TailFrom(file))
{
Console.WriteLine($"line read= {line}");
}
- 1. ¿Cómo leer el archivo XML en C#?
- 2. ¿Cómo leer el archivo binario en C#?
- 3. C++ Leer archivo hasta el espacio
- 4. Cómo instalar C++ continuamente en Hudson/Jenkins
- 5. C# - Leer bytes específicos de un archivo
- 6. ¿Cómo se lee continuamente un archivo en Java?
- 7. Problema al leer el archivo XML en C# DataSet
- 8. Cómo leer el archivo abierto de Excel en C#
- 9. leer el archivo de texto mediante programación usando Objective-C
- 10. al leer el archivo app.config
- 11. ¿Cómo leer el archivo .class?
- 12. leer el archivo en classpath
- 13. Leer archivos CSV desde el archivo Zip
- 14. Archivo de registro de script Bash para mostrar continuamente
- 15. Reproducción de música continuamente con el nombre
- 16. El clip de audio no repetirá continuamente
- 17. Plugin M2E actualizando continuamente el índice
- 18. Leer del archivo en Eclipse
- 19. leyendo continuamente de una secuencia?
- 20. leer el archivo xml usando http
- 21. Manejando NSError al leer desde el archivo?
- 22. Cómo leer el archivo XML en Android
- 23. Leer el archivo XLSX en Java
- 24. leer el archivo db SQLite usando java
- 25. Cómo leer el archivo JSON con Dojo
- 26. ¿Cómo leer el archivo .arff con R?
- 27. al leer el archivo utilizando fgets
- 28. arrayWithContentsOfFile no puede leer el archivo plist
- 29. matrices asociativas al leer el archivo
- 30. Cómo leer el archivo completo con bitstring
¿Por qué 1024? ¿Por qué binnary? Ejemplo? –
@Dmytro: Ver mi publicación actualizada. –
Si se escribieron más o menos de 1024 bytes desde el último control, ¿esto no omitirá algunos datos o leerá algunos datos dos veces? – baruch