我正在尝试在每帧读取流中的字节。 我希望能够读取存储在我创建的文件中的位置和时间戳信息。
流是记录的骨架数据流,它采用编码的二进制格式
Stream recordStream;
byte[] results;
using (FileStream SourceStream = File.Open(@".....\Stream01.recorded", FileMode.Open))
{
if (SourceStream.CanRead)
{
results = new byte[recordStream.Length];
SourceStream.Read(results, 0, (int)recordStream.Length);
}
}
应该读取文件,并且Read方法应该在推进流中的位置之前读取当前的字节序列。
有没有办法从读取的字节中提取出我想要的数据(位置和时间戳),并在它前进之前将其保存在单独的变量中?
使用二进制阅读器可以为我提供执行此操作的功能。
BinaryReader br1 = new BinaryReader(recordStream);
我已将文件另存为.recorded。我还将它保存为.txt以查看文件中包含的内容,但由于它是编码的,因此无法理解。
更新: 我尝试使用断点运行代码以查看它是否使用我的二进制读取器进入函数并且它崩溃并出现错误:ArgumentException未处理。在BinaryReader初始化和声明
上,Stream无法读取BinaryReader br1 = new BinaryReader(recordStream);
文件类型为.recorded。
答案 0 :(得分:2)
您未提供有关您尝试阅读的数据格式的任何信息 但是,使用BinaryReader正是您需要做的。
它公开了从流中读取数据并将其转换为各种类型的方法。
请考虑以下示例:
var filename = "pathtoyourfile";
using (var stream = File.Open(filename, FileMode.Open))
using(var reader = new BinaryReader(stream))
{
var x = reader.ReadByte();
var y = reader.ReadInt16();
var z = reader.ReadBytes(10);
}
这实际上取决于你的数据格式。
<强>更新强>
即使我觉得我已经提供了你需要的所有信息,
让我们使用你的数据。
您说数据中的每条记录都以
开头[long:timestamp] [int:framenumber]
using (var stream = File.Open(filename, FileMode.Open))
using(var reader = new BinaryReader(stream))
{
var timestamp = reader.ReadInt64();
var frameNumber = reader.ReadInt32();
//At this point you have the timestamp and the frame number
//you can now do whatever you want with it and decide whether or not
//to continue, after that you just continue reading
}
如何继续阅读取决于记录剩余部分的格式 如果记录中的所有字段都有特定的长度,那么你要么(取决于 你知道时间戳和帧号的值的选择继续 读取该记录的所有字段,或者只是前进到流中的某个位置 包含下一条记录。例如,如果每个记录长度为100个字节,如果要在获得前两个字段后跳过此记录:
stream.Seek(88, SeekOrigin.Current);
//88 here because the first two fields take 12 bytes -> (100 - 8 + 4)
如果记录的长度可变,则解决方案类似,但您必须这样做 考虑各个领域的长度(应由...定义) 变长字段之前的长度字段)
至于知道前8个字节是否真的代表时间戳, 没有真正知道的方法......记住最后流只包含 一系列单独的字节,除了含义之外没有任何意义 通过您的文件格式给他们。您必须修改文件格式,或者您可以 尝试检查上例中“timestamp”的值是否有意义。
这是您自己定义的文件格式,如果是这样的话......也许您正在将其变得复杂,并且可能希望查看Google Protocol Buffers或Apache Thrift等解决方案。
如果这仍然不是您想要的,您将不得不重新定义您的问题。
答案 1 :(得分:1)
根据您的意见:
您需要知道整个文件的确切定义。您可以基于以下文件格式创建结构:
struct YourFileFormat {
[FieldOffset(0)]
public long Timestamp;
[FieldOffset(8)]
public int FrameNumber;
[FieldOffset(12)]
//.. etc..
}
然后,使用BinaryReader
,您可以为每个帧单独读取每个字段:
// assume br is an instantiated BinaryReader..
YourFileFormat file = new YourFileFormat();
file.Timestamp = br.ReadInt64();
file.FrameNumber = br.ReadInt32();
// etc..
或者,您可以阅读整个文件并让编组类将所有内容复制到结构中。
byte[] fileContent = br.ReadBytes(sizeof(YourFileFormat));
GCHandle gcHandle = GCHandle.Alloc(fileContent, GCHandleType.Pinned); // or pinning it via the "fixed" keyword in an unsafe context
file = (YourFileFormat)Marshal.PtrToStructure(gcHandle.AddrOfPinnedObject(), typeof(YourFileFormat));
gcHandle.Free();
但是,这假设您将知道文件的确切大小。虽然这个方法虽然..每个帧(假设你知道有多少)可以是这个结构中的一个固定大小的数组,以便工作。
结论:除非您知道要跳过的内容的大小,否则您无法从您需要的文件中获取数据。