c # - la lettura dal file di log binario che viene aggiornato ogni 6 secondi con 12k dei dati

StackOverflow https://stackoverflow.com/questions/1170538

  •  19-09-2019
  •  | 
  •  

Domanda

Ho un file di log binario con i dati di streaming da un sensore (Int16).
vengono aggiunti ogni 6 secondi, 6000 campioni di tipo Int16, finché viene disinserito il sensore.

Ho bisogno di interrogare questo file ad intervalli regolari, continuando dall'ultima posizione leggere. E 'meglio a) mantenere un filestream e lettore binario aperto e istanziata tra le letture b) istanziare filestream e lettore binario ogni volta che ho bisogno di leggere (e mantenere una variabile esterna per tracciare l'ultima posizione letta) c) qualcosa di meglio?

EDIT: Alcuni grandi suggerimenti finora, hanno bisogno di aggiungere che l'applicazione "server" viene fornito da un fornitore fonte esterna e non può essere modificato

.
È stato utile?

Soluzione

Se è sempre aggiungendo la stessa quantità di dati, può avere senso per riaprirlo. Si potrebbe desiderare di scoprire la lunghezza prima di aprirlo, e poi arrotondare al numero intero di "set di campioni" disponibili, nel caso in cui si cattura mentre è ancora la scrittura dei dati. Questo può significare che leggete meno di potrebbero leggi (se finisce la scrittura tra voi controllare la lunghezza e l'avvio di lettura), ma ti cattura la prossima volta.

È necessario assicurarsi di utilizzare opportune opzioni di condivisione in modo che lo scrittore può ancora scrivere mentre si sta leggendo però. (Lo scrittore avrà probabilmente essere stato scritto con questo in mente anche.)

Altri suggerimenti

Si può utilizzare MemoryMappedFiles ?

Se è possibile, la mappatura del file in memoria e la condivisione fra i processi si sarà in grado di leggere i dati semplicemente incrementando l'offset per il puntatore ogni volta.

Se si combinano con un evento è possibile segnalare il lettore quando si può andare in un leggere le informazioni. Non ci sarà alcun bisogno di bloccare qualsiasi cosa come il lettore sarà sempre leggere i dati "vecchi" che è già stato scritto.

Ti consiglio di utilizzare i tubi, si comportano proprio come i file, ad eccezione dei dati del flusso direttamente tra le applicazioni, anche se le applicazioni eseguite su diversi PC (anche se questo è davvero solo un'opzione se si è in grado di modificare entrambe le applicazioni). Check it out sotto il namespace "System.IO.Pipes".

P.S. Si potrebbe utilizzare un tubo "di nome" per questo (i tubi sono supportati in 'c' e, in modo praticamente qualsiasi mezzo decente linguaggio di programmazione dovrebbe essere in grado di attuarle)

Credo che (a) è il migliore perché:

  • posizione attuale verrà incrementato, come si legge e non c'è bisogno di preoccuparsi di memorizzare da qualche parte;
  • Non è necessario aprirlo e cercare la posizione desiderata (non dovrebbe essere molto più lento di riaprire ma mantenendo aperta dà OS alcuni suggerimenti per l'ottimizzazione credo) ogni volta che si effettua il prelevamento esso;
  • Altre soluzioni che posso pensare fuori richiede PInvokes a primitive di sincronizzazione tra processi di sistema. E non sarà più veloce di operazioni sui file già in quadro.

Hai solo bisogno di impostare flag FileShare corrette:

Proprio per esempio:

Server:

using(var writer = new BinaryWriter(new FileStream(@"D:\testlog.log", FileMode.Append, FileAccess.Write, FileShare.Read)))
{
    int n;
    while(Int32.TryParse(Console.ReadLine(), out n))
    {
        writer.Write(n);
        writer.Flush(); // write cached bytes to file
    }
}

Cliente:

using (var reader = new BinaryReader(new FileStream(@"D:\testlog.log", FileMode.Open, FileAccess.Read, FileShare.ReadWrite)))
{
    string s;
    while (Console.ReadLine() != "exit")
    {
        // allocate buffer for new ints
        Int32[] buffer = new Int32[(reader.BaseStream.Length - reader.BaseStream.Position) / sizeof(Int32)];

        Console.WriteLine("Stream length: {0}", reader.BaseStream.Length);
        Console.Write("Ints read: ");
        for (int i = 0; i < buffer.Length; i++)
        {
            buffer[i] = reader.ReadInt32();
            Console.Write((i == 0 ? "" : ", ") + buffer[i].ToString());
        }
        Console.WriteLine();
    }
}

si potrebbe anche trasmettere i dati in un database, piuttosto che un file come un'altra alternativa, allora non avrebbe dovuto preoccuparsi di blocco dei file.

, ma se sei bloccato con il metodo del file, si consiglia di chiudere il file ogni volta che si legge i dati da esso; dipende da come un sacco complicato processo scrittura nel file sarà, e se può rilevare un file operazione di bloccaggio e rispondere adeguatamente senza crash orribilmente.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top