c# - 从二进制日志文件中读取每 6 秒更新一次的 12k 数据
-
19-09-2019 - |
题
我有一个二进制日志文件,其中包含来自传感器(Int16)的流数据。
每 6 秒添加 6000 个 Int16 类型的样本,直到传感器断开连接。
我需要定期轮询该文件,从上次读取的位置继续。a)在读取之间保持文件流和二进制读取器的打开和实例化b)每次我需要阅读时实例化文件流和二进制读取器(并保留外部变量以跟踪最后一个位置读取)c)c)更好吗?
编辑:到目前为止,一些很好的建议需要补充一点,“服务器”应用程序是由外部源供应商提供的,无法修改。
解决方案
如果它总是将相同的数据量,这可能是有意义的重新打开它。你可能想找出长度在打开它之前,然后向下舍入的“样本集”的可用整数,以防万一你抓住它,而它仍然写入数据。这可能意味着你读不到你的可能的读取(如果你写检查长度和开始读之间完成),但下一次你会赶上。
您需要确保您使用适当的共享选项,这样,当你阅读虽然笔者仍然可以写。 (作者可能要一直记住这个写得太)
其他提示
您可以使用 MemoryMappedFiles ?
如果可以的话,该文件映射在存储器和进程之间共享它你将能够通过简单地将您的指针偏移每次递增来读取数据。
如果你与你可以通知你的读者的事件结合起来的时候,他可以在去读取信息。将不会有必要阻止任何东西作为读者总是读这已经被写入“旧”的数据。
我会建议使用的管道,他们的行为就像文件,除了直接应用程序之间的数据流,即使应用程序在不同的PC上运行(虽然这是真的只有一个选择,如果你能够改变这两个应用程序)。检查它根据“System.IO.Pipes”命名空间。
P.S。你可以使用“命名的”管这(管道支持“C”为好,所以基本上任何像样的编程语言应该能够实现它们)
我认为 (a) 是最好的,因为:
- 当前位置会随着您的阅读而增加,您无需担心将其存储在某个地方;
- 每次轮询时,您不需要打开它并寻找所需的位置(重新打开它应该不会慢很多,但保持打开状态会给操作系统一些优化提示);
- 我能想到的其他解决方案需要 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();
}
}
您还可以将数据流转换成一个数据库,而不是一个文件作为另一种选择,那么你就不必担心文件锁定。
但如果你坚持用文件的方法,您可能希望每次从中读取数据时,关闭文件;它很多取决于过程写入文件如何复杂将是,是否可以检测到一个文件锁定操作,并适当地不可怕崩溃响应。