0

我正在尝试在每一帧读取流中的字节。我希望能够读取存储在我创建的文件中的位置和时间戳信息。

流是记录的骨架数据流,采用编码二进制格式

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 以查看文件中包含的内容,但由于它是编码的,因此无法理解。

更新:我尝试使用断点运行代码以查看它是否使用我的 binaryreader 进入函数并崩溃并出现错误:ArgumentException 未处理。在 BinaryReader 初始化和声明时,流不可读

BinaryReader br1 = new BinaryReader(recordStream);

文件类型为 .recorded。

4

2 回答 2

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

不过,这实际上取决于您的数据格式。

更新
尽管我觉得我已经提供了你需要的所有信息,让我们使用你的数据。

您说数据中的每条记录都以

[长:时间戳] [整数:帧号]

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 个字节是否真的代表时间戳,没有真正的方法可以确定...请记住,流最后只包含一系列单独的字节,除了赋予它们的含义之外,这些字节没有任何意义通过您的文件格式。您必须修改文件格式,或者您可以尝试检查上面示例中的“时间戳”的值是否有意义。

这是您自己定义的文件格式吗?如果是...也许您正在使它变得复杂,并且可能想要查看诸如 Google Protocol Buffers 或 Apache Thrift 之类的解决方案。

如果这仍然不是您想要的,您将不得不重新定义您的问题。

于 2012-12-11T05:47:15.613 回答
1

根据您的评论:

您需要知道整个文件的确切定义。您基于此文件格式创建一个结构:

struct YourFileFormat {
    [FieldOffset(0)]
    public long Timestamp;

    [FieldOffset(8)]
    public int FrameNumber;

    [FieldOffset(12)]
    //.. etc..
}

然后,使用 a 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();

但是,这假设您知道文件的确切大小。但是,使用这种方法.. 每一帧(假设您知道有多少)都可以是该结构中的一个固定大小的数组,以使其正常工作。

底线:除非您知道要跳过的内容的大小..您不能希望从您需要的文件中获取数据。

于 2012-12-11T08:46:55.200 回答