我有一个二进制日志文件,其中包含来自传感器(Int16)的流数据 每隔6秒,就会添加6000个Int16类型的样本,直到传感器断开连接。
我需要定期轮询此文件,从上次位置读取继续。 是不是更好 a)保持文件流和二进制阅读器打开并在读数之间实例化 b)每次我需要读取时实例化文件流和二进制读取器(并保留一个外部变量来跟踪最后读取的位置) c)更好的东西?
编辑:到目前为止一些很棒的建议,需要补充一点,“服务器”应用程序由外部源供应商提供,无法修改。
答案 0 :(得分:2)
如果它总是添加相同数量的数据,则重新打开它可能是有意义的。你可能想要在打开之前找出它的长度,然后向下舍入到可用的整个“样本集”,以防你在它仍然在写数据时捕获它。这可能意味着你阅读的内容少于可能读取的内容(如果你在检查长度和开始阅读之间完成了写操作),那么下次你就会赶上来。
您需要确保使用适当的共享选项,以便作者在您阅读时仍然可以写作。 (作者可能也必须考虑到这一点。)
答案 1 :(得分:2)
您可以使用MemoryMappedFiles吗?
如果可以,将文件映射到内存中并在进程之间共享,只需每次递增指针的偏移量,就可以读取数据。
如果您将其与活动结合使用,您可以在读取信息时向读者发出信号。没有必要阻止任何东西,因为读者总是会读取已经写过的“旧”数据。
答案 2 :(得分:2)
我建议使用管道,它们就像文件一样,除了直接在应用程序之间流数据,即使应用程序在不同的PC上运行(尽管如果你能够更改这两个应用程序,这只是一个选项)。在“System.IO.Pipes”命名空间下查看。
P.S。你可以使用“命名”管道('c'也支持管道,所以基本上任何一半不错的编程语言都应该能够实现它们)
答案 3 :(得分:1)
我认为(a)是最好的,因为:
您只需设置正确的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();
}
}
答案 4 :(得分:0)
您也可以将数据流式传输到数据库中,而不是将文件作为另一种方式传输,然后您就不必担心文件锁定了。
但是如果您坚持使用文件方法,则可能需要在每次从中读取数据时关闭该文件;它取决于写入文件的过程有多复杂,以及它是否可以检测到文件锁定操作并做出适当的响应而不会崩溃。