4

センサー(Int16)からのストリーミングデータを含むバイナリログファイルがあります。
センサーが切断されるまで、6秒ごとにタイプInt16の6000サンプルが追加されます。

最後に読み取った位置から続けて、このファイルを定期的にポーリングする必要があります。a)ファイルストリームとバイナリリーダーを開いたままにして、読み取りの間にインスタンス化するb)読み取る必要があるたびにファイルストリームとバイナリリーダーをインスタンス化する(そして最後に読み取った位置を追跡するために外部変数を保持する)c)何か良いものがありますか?

編集:これまでのいくつかの素晴らしい提案は、「サーバー」アプリが外部のソースベンダーによって提供されており、変更できないことを追加する必要があります。

4

5 に答える 5

2

パイプを使用することをお勧めします。パイプはファイルと同じように機能しますが、アプリが異なるPCで実行されている場合でも、アプリケーション間で直接データをストリーミングする点が異なります(ただし、これは両方のアプリケーションを変更できる場合の唯一のオプションです)。「System.IO.Pipes」名前空間で確認してください。

PSこれには「名前付き」パイプを使用します(パイプは「c」でもサポートされているため、基本的には、半分まともなプログラミング言語で実装できるはずです)

于 2009-07-23T10:54:33.543 に答える
2

常に同じ量のデータを追加している場合は、再度開くのが理にかなっている場合があります。開く前に長さを調べてから、データの書き込み中にキャッチした場合に備えて、使用可能な「サンプルセット」の総数に切り捨てることができます。これは、読み取ることができるよりも少ない読み取りを意味する場合があります(長さを確認してから読み取りを開始するまでの間に書き込みが終了した場合)が、次回は追いつくでしょう。

ただし、読んでいる間もライターが書き込めるように、適切な共有オプションを使用していることを確認する必要があります。(ライターはおそらくこれを念頭に置いて書かれている必要があります。)

于 2009-07-23T09:08:14.660 に答える
2

MemoryMappedFilesを使用できますか?

可能であれば、メモリ内のファイルをマッピングしてプロセス間で共有することで、ポインタのオフセットを毎回インクリメントするだけでデータを読み取ることができます。

それをイベントと組み合わせると、読者が情報を読むことができるときに読者に合図することができます。リーダーはすでに書き込まれた「古い」データを常に読み取るため、何もブロックする必要はありません。

于 2009-07-23T09:16:35.783 に答える
1

(a)が最適だと思います。理由は次のとおりです。

  • 現在の位置は読むにつれて増加し、どこかに保存することを心配する必要はありません。
  • ポーリングするたびに、開いて必要な位置を探す必要はありません(再度開くのにそれほど時間がかかることはありませんが、開いたままにしておくと、OSに最適化のヒントが得られます)。
  • 私が考えることができる他の解決策は、システム間同期プリミティブをシステム化するためにPInvokesを必要とします。また、すでにフレームワークにあるファイル操作よりも高速になることはありません。

適切なFileShareフラグを設定する必要があります。

ちょうど例:

サーバ:

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
    }
}

クライアント:

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();
    }
}
于 2009-07-23T10:47:44.023 に答える
0

別の方法としてファイルではなくデータベースにデータをストリーミングすることもできます。そうすれば、ファイルのロックについて心配する必要はありません。

ただし、fileメソッドに固執している場合は、ファイルからデータを読み取るたびにファイルを閉じることをお勧めします。これは、ファイルへの書き込みプロセスがどれほど複雑になるか、およびファイルのロック操作を検出して、ひどくクラッシュすることなく適切に応答できるかどうかに大きく依存します。

于 2009-07-23T09:21:40.813 に答える