C# - 12kのデータで6秒ごとに更新されるバイナリログファイルからの読み取り
-
19-09-2019 - |
質問
センサー (Int16) からのストリーミング データを含むバイナリ ログ ファイルがあります。
センサーが切断されるまで、6 秒ごとにタイプ Int16 の 6000 サンプルが追加されます。
最後に読み取られた位置から継続して、定期的にこのファイルをポーリングする必要があります。a)フィルストリームとバイナリリーダーを開いて測定値の間にインスタンス化する方が良いですb)Filestreamとバイナリリーダーを読む必要があるたびに(そして最後の位置を追跡するために外部変数を追跡する)c)より良いもの?
編集:これまでのところ、いくつかの優れた提案には、「サーバー」アプリが外部ソース ベンダーによって提供されており、変更できないことを追加する必要があります。
解決
それは常に同じ量のデータを追加するなら、それはそれを再度開くことに意味を行うことができます。あなたは、あなたがそれを開く前に、長さを知りたい、そしてそれはまだデータを書いている間、あなたがそれをキャッチ念のために、利用できる「サンプルセット」の整数に切り捨てかもしれません。それはは(あなたは長さをチェックして、読み取りを開始するとの書き込みが終了している場合)読むことができたが、あなたは次の時間を追いつくだろう。
あなたはをより少なくを読ん意味するかもしれませんあなたはあなたがが読んでいる間、筆者はまだ書くことができるようにあなたが適切な共有オプションを使用していることを確認する必要があります。 (筆者はおそらくあまりにもこれを念頭において書かれている必要があります。)
他のヒント
あなたが使用することはできます MemoryMappedFiles の?
あなたができる場合は、メモリ内のファイルをマッピングし、あなたは、単にたびにポインタのオフセットをインクリメントすることにより、データを読み取ることができますプロセス間でそれを共有します。
あなたがあなたの読者に信号を送ることができるイベントとそれを組み合わせる場合は、とき、彼は情報をお読みに行くことができます。読者は常にすでに書き込まれている「古い」データを読み込みますよう何かをブロックする必要はありません。
私はパイプを使用することをお勧めします、彼らはアプリは別のPC上で実行した場合でも、直接アプリケーション間のストリームデータを除いて、単にファイルのように振る舞います。 「System.IO.Pipes」名前空間の下でそれをチェックしてください。
P.S。このため、「名前付き」パイプ(パイプも同様に「C」でサポートされているので、基本的に任意の半分のまともなプログラミング言語は、それらを実装することができるはずです)。
を使用します次の理由から、(a) が最適だと思います。
- 現在の位置は読み込むにつれてインクリメントされるので、それをどこかに保存することを心配する必要はありません。
- ポーリングするたびに、それを開いて必要な位置を探す必要はありません(再度開くとそれほど遅くなるはずはありませんが、開いたままにしておくと、OSに最適化のためのヒントが与えられると思います)。
- 私が考えられる他の解決策では、システムプロセス間同期プリミティブに PInvoke が必要です。また、フレームワークにすでに組み込まれているファイル操作よりも高速になることはありません。
必要なのは、適切な 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();
}
}
あなたも、あなたは、ファイルのロックを心配する必要はないだろう、別の代替として、ファイルではなく、データベースにデータをストリームすることができます。
しかし、あなたはファイル方式で立ち往生している場合は、ファイルにあなたがそれからデータを読み込むたびに閉鎖することができます。それはファイルへの書き込みプロセスがあることを行っている方法を複雑にたくさん依存し、かどうか、それは操作をロックファイルを検出することができますし、恐ろしくクラッシュすることなく適切に対応ます。