我正在尝试使用C#读取二进制数据。 我有关于我想要阅读的文件中数据布局的所有信息。 我能够读取数据“chunk by chunk”,即获取前40个字节的数据将其转换为字符串,获得接下来的40个字节。

由于至少有三种略有不同的数据版本,我想将数据直接读入结构中。 它只是通过“逐行”阅读而感觉更加正确。

我尝试了以下方法但无济于事:

StructType aStruct;
int count = Marshal.SizeOf(typeof(StructType));
byte[] readBuffer = new byte[count];
BinaryReader reader = new BinaryReader(stream);
readBuffer = reader.ReadBytes(count);
GCHandle handle = GCHandle.Alloc(readBuffer, GCHandleType.Pinned);
aStruct = (StructType) Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(StructType));
handle.Free();

该流是一个打开的FileStream,我已经开始从中读取。 使用Marshal.PtrToStructure时,我得到一个AccessViolationExceptio

由于我对文件末尾的数据不感兴趣,因此该流包含的信息比我尝试阅读的要多。

结构定义如下:

[StructLayout(LayoutKind.Explicit)]
struct StructType
{
    [FieldOffset(0)]
    public string FileDate;
    [FieldOffset(8)]
    public string FileTime;
    [FieldOffset(16)]
    public int Id1;
    [FieldOffset(20)]
    public string Id2;
}

示例代码从原始代码更改为使此问题更短。

如何将二进制数据从文件读入结构?

===============>>#1 票数:28

问题是结构中的字符串 s。 我发现像byte / short / int这样的编组类型不是问题; 但是当你需要编组成一个复杂的类型(如字符串)时,你需要你的结构显式地模仿非托管类型。 您可以使用MarshalAs attrib执行此操作。

对于您的示例,以下应该工作:

[StructLayout(LayoutKind.Explicit)]
struct StructType
{
    [FieldOffset(0)]
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)]
    public string FileDate;

    [FieldOffset(8)]
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)]
    public string FileTime;

    [FieldOffset(16)]
    public int Id1;

    [FieldOffset(20)]
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 66)] //Or however long Id2 is.
    public string Id2;
}

===============>>#2 票数:11

这是我正在使用的。
这成功地为我阅读可移植可执行格式。
它是一个通用函数,所以T是你的struct类型。

public static T ByteToType<T>(BinaryReader reader)
{
    byte[] bytes = reader.ReadBytes(Marshal.SizeOf(typeof(T)));

    GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
    T theStructure = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
    handle.Free();

    return theStructure;
}

===============>>#3 票数:6

正如罗尼所说,我会使用BinaryReader并分别读取每个字段。 我找不到带有此信息的文章的链接,但据观察,如果struct包含少于30-40个字段,使用BinaryReader读取每个单独的字段可能比Marshal.PtrToStruct更快。 当我找到它时,我会发布文章的链接。

该文章的链接位于: http//www.codeproject.com/Articles/10750/Fast-Binary-File-Reading-with-C

当编组结构数组时,PtrToStruct可以更快地获得上风,因为您可以将字段计数视为字段*数组长度。

===============>>#4 票数:3

我没有运气使用BinaryFormatter,我想我必须有一个完全匹配文件内容的完整结构。 我意识到最后我对文件内容并不感兴趣,所以我选择了将部分流读取到bytebuffer然后使用它转换它的解决方案。

Encoding.ASCII.GetString()

对于字符串和

BitConverter.ToInt32()

对于整数。

我需要能够稍后解析更多的文件,但是对于这个版本,我只需要几行代码就可以了。

===============>>#5 票数:2

我没有看到您的代码有任何问题。

只是出于我的想法,如果你试图手动怎么办? 它有用吗?

BinaryReader reader = new BinaryReader(stream);
StructType o = new StructType();
o.FileDate = Encoding.ASCII.GetString(reader.ReadBytes(8));
o.FileTime = Encoding.ASCII.GetString(reader.ReadBytes(8));
...
...
...

也试试

StructType o = new StructType();
byte[] buffer = new byte[Marshal.SizeOf(typeof(StructType))];
GCHandle handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
Marshal.StructureToPtr(o, handle.AddrOfPinnedObject(), false);
handle.Free();

然后在BinaryReader中使用buffer []而不是从FileStream读取数据,看看你是否仍然得到AccessViolation异常。

我没有运气使用BinaryFormatter,我想我必须有一个完全匹配文件内容的完整结构。

这是有道理的,BinaryFormatter有自己的数据格式,与你的完全不兼容。

===============>>#6 票数:0

直接阅读结构是邪恶的 - 许多C程序因为不同的字节顺序,字段的不同编译器实现,打包,字大小而落后......

您最好逐字节串行化和反序列化。 如果你想要或者只是习惯了BinaryReader,请使用build in stuff。

===============>>#7 票数:0

试试这个:

using (FileStream stream = new FileStream(fileName, FileMode.Open))
{
    BinaryFormatter formatter = new BinaryFormatter();
    StructType aStruct = (StructType)formatter.Deserialize(filestream);
}

  ask by Robert Höglund translate from so

未解决问题?本站智能推荐:

1回复

如何使void指针读取二进制文件的给定部分

我有一个二进制文件,其中包含3个不同的结构和一个圣诞文本。 在二进制文件的第一行,他们为我提供了一个int,它表示文件中包的大小。 一个包包含3个结构,chistmastext和大小。 结构位于一个名为framehdr.h的文件中,我正在读取的二进制文件称为TCPdump。 现在我正
2回复

如何将大型二进制文件读入结构中以提高性能?

我有一些大的二进制文件,我将它们读入结构中,然后将这些结构添加到列表中,以便稍后在它们中进行遍历。 一切工作正常,但读入结构的速度比预期的慢。 以下是相关代码: 我遍历我拥有的二进制文件列表,并在每个文件上打开一个文件流,跳至二进制文件中第一个“结构”出现的位置,然后将其读入结构,然
2回复

打印二进制序列c ++的一部分

我已经从二进制文件中读取了一些结构指针。 在我的结构中,有几个unsigned int整数。 这是我的结构: 编辑 我用以下行读取二进制文件: 现在,我想访问var1的值,但是我不知道该怎么做? 有没有人可以帮助我? 提前致谢。
4回复

C#加载二进制文件

请告诉我最好/最快的方法: 1)将很小的二进制文件加载到内存中。 例如图标; 2)加载/读取大小为512Mb +的非常大的二进制文件。 3)当您不想考虑大小/速度而只能做的事情时,您通常会选择:将所有字节读入内存吗? 谢谢!!! PS对不起,也许是一个琐碎的问题。
1回复

Fortran从C#读取二进制文件

我正在尝试阅读fortran中的二进制文件。 该文件在c#中创建。 在我的下面的例子中它只存储到整数(我假设4字节,因为创建的文件大小是8字节): 用于读取数据的fortran代码: open和inquire命令运行没有问题。 在调试模式下,它报告在open ios为0并且
2回复

在C ++中向文件写入不同的结构? [关闭]

我需要一种将三种不同类型的结构写入二进制文件的方法,以后必须对其进行搜索。 (例如,在struct A中有两个字段,一个int和一个char;在struct B中有int和long;我需要输出所有int等于键盘给定的结构)。 我知道如何将相同类型的结构写入文件以及如何搜索它们,但是我只是
1回复

使用多种类型的C ++从文件中读取结构

我正在使用下面的代码从二进制文件读取结构。 假定二进制文件中有多个结构,类型为struct A,struct B和struct C,文件中出现的大小不同。 如果我想按顺序阅读所有内容,假设我知道顺序,这是正确的吗?
2回复

将Python中的二进制文件读入结构

我如何去在Python打开二进制数据文件和回读值一个long的时间,到一个结构。 我目前有这样的东西,但我认为这将继续覆盖idList ,我想附加到它idList ,所以最后得到一个文件中所有long值的元组-
2回复

如何加快二进制读/写

我有这个代码 发生的情况是,程序从一个非常大的文件(17 GB)中的不同位置读取了两个long,将它们相加/相减,然后在相同位置重写了新值。 据我所知,读取数据的最有效方法是将大块读入缓冲区,然后使用该缓冲区。 但是,这种方法在这里行不通,因为基于pt和j的值,它可能是从文件的开
1回复

二进制文件中的字符串,结构?

但是这部分一直显示为错误 我试图让用户写一个名称,如果该名称长于10个字母,它将被切断,或更短的名称将添加空格。 还可以请有人解释为什么不能将字符串写入二进制文件吗? 如果我使用字符串,为什么还要使用结构而不是类。