Chcę czytać plik w sposób ciągły jak ogon GNU z parametrem "-f". Potrzebuję go do odczytu dziennika na żywo. Co to jest właściwy sposób?C# ciągły odczyt pliku
Odpowiedz
Chcesz otworzyć FileStream
w trybie binarnym. Okresowo, szukaj końca pliku minus 1024 bajty (lub cokolwiek innego), a następnie odczytaj na końcu i na wyjściu. Tak działa tail -f
.
Odpowiedzi na pytania:
Binary ponieważ trudno jest losowo dostępu do pliku, jeśli czytasz to jako tekst. Musisz samemu dokonać konwersji binarnej na tekst, ale nie jest to trudne. (Zobacz poniżej)
1024 bajtów, ponieważ jest to miły wygodny numer i powinien obsługiwać 10 lub 15 linii tekstu. Zazwyczaj.
Oto przykład otwierania pliku, czytając ostatnie 1024 bajtów i przekształcenie go do tekstu:
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);
}
}
Pamiętaj, że musisz otworzyć z FileShare.ReadWrite
, ponieważ próbujesz odczytać plik, który jest aktualnie otwarty do pisania innym procesem.
Należy również pamiętać, że użyłem Encoding.Default
, który w języku angielskim/amerykańskim i dla większości zachodnioeuropejskich języków będzie oznaczał 8-bitowe znaki. Jeśli plik jest zapisany w innym kodowaniu (jak kodowanie UTF-8 lub inne kodowanie Unicode), możliwe, że bajty nie zostaną poprawnie przekonwertowane na znaki. Będziesz musiał sobie z tym poradzić, określając kodowanie, jeśli uważasz, że to będzie problem. Przeszukaj przepełnienie stosu w poszukiwaniu informacji o określaniu kodowania tekstu pliku.
Jeśli chcesz robić to okresowo (na przykład co 15 sekund), możesz ustawić zegar, który będzie wywoływał metodę ReadTail
tak często, jak chcesz. Możesz trochę zoptymalizować, otwierając plik tylko raz na początku programu. To zależy od Ciebie.
Można użyć klasy FileSystemWatcher, która może wysyłać powiadomienia o różnych zdarzeniach zachodzących w systemie plików, takich jak zmieniony plik.
OK. Powiedzmy, że otrzymałem zdarzenie, że plik został zmieniony. Jak mogę przeczytać do końca z pozycji, którą skończyłem czytać po raz ostatni? Przykład Eny doceniony :) –
Jeśli tylko szukasz narzędzie to zrobić to sprawdź darmową wersję Bare tail
Nie, nie szukam narzędzia. Potrzebuję sposobu, aby zaimplementować go w C# dla mojego programu. –
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);
}
bardziej naturalne podejście z użyciem 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();
Tutaj główny cykl odczyt przestaje czekać na danych przychodzących i FileSystemWatcher
służy tylko obudzić główny cykl odczytu.
Aby nieprzerwanie monitorować koniec pliku, wystarczy wcześniej zapamiętać długość pliku.
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);
}
}
musiałem użyć ASCIIEncoding, ponieważ kod ten nie jest wystarczająco silny, aby zaspokoić zmiennych długościach charakter UTF8 na granicach buforowych.
Uwaga: Można zmienić pozycję Thread.Sleep na różne taktowania, a także można powiązać ją z mechanizmem tworzenia pliku i schematem blokowania - Monitor.Enter/Wait/Pulse. Dla mnie zegar wystarcza, a co najwyżej sprawdza długość pliku co sekundę, jeśli plik się nie zmienił.
To jest moje rozwiązanie
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);
}
}
}
tak, to w kodzie można zrobić
foreach (string line in TailFrom(file))
{
Console.WriteLine($"line read= {line}");
}
- 1. C++ Odczyt pliku PDF
- 2. Jak utworzyć nieblokujący ciągły odczyt z `stdin`?
- 3. C# PCL odczyt z pliku
- 4. Odczyt pliku w ścieżce sieciowej
- 5. Zapis/odczyt pliku plist iPhone
- 6. Odczyt pliku do wektora naraz
- 7. tablice asocjacyjne odczyt z pliku
- 8. odczyt/zapis obiektu do pliku
- 9. angularjs odczyt z pliku właściwości
- 10. C++ LibTiff - Odczyt i zapisanie pliku zi do pamięci
- 11. C# odczyt pliku CSV nie daje poprawną ścieżkę
- 12. Odczyt strumienia stdin w pliku wsadowym
- 13. Odczyt/zapis do plików binarnych w C
- 14. C odczyt i bezpieczeństwo wątków (linux)
- 15. node.js/odczyt 100 pierwszych bajtów pliku
- 16. FlatBuffers: Zapis i odczyt z pliku binarnego?
- 17. Java: odczyt i zapis pliku CSV
- 18. Odczyt i kodowanie base64 pliku binarnego
- 19. Jak drogi jest odczyt właściwości pliku? .NET
- 20. zapis/odczyt pliku binarnego w Nim
- 21. Odczyt z pliku CSV w programie MATLAB
- 22. d3 - odczyt danych JSON zamiast pliku CSV
- 23. dekompresja i odczyt pliku gzip w scala
- 24. phonegap odczyt i zapis pliku json
- 25. odczyt danych z plików matlab język C
- 26. USB HID wisi na Odczyt() w C#
- 27. odczyt pliku tekstowego z powrotem do słownika za pomocą json.loads
- 28. Jak naprawić błąd ValueError: odczyt wyjątku zamkniętego pliku?
- 29. C/C++ BLE odczyt/zapis przykład z Bluez
- 30. Wiosna Boot - Odczyt pliku tekstowego za pomocą ResourceLoader
Dlaczego 1024? Dlaczego binnary? Przykład? –
@Dmytro: Zobacz mój zaktualizowany post. –
Jeśli od ostatniego sprawdzenia zapisano mniej lub więcej niż 1024 bajty, czy nie pominąłoby to niektórych danych lub dwóch danych? – baruch