gpt4 book ai didi

c# - 将二进制数据加载到结构中

转载 作者:行者123 更新时间:2023-11-30 18:11:29 25 4
gpt4 key购买 nike

我正在尝试使用从 byte[] 加载的数据填充结构(不必是实际结构)。

byte[]中有多种不同的数据结构,其中一种是字符串,声明为:

UInt16 stringLenght
byte[stringLenght] zeroTerminatedString

在“c”语言中,这可以通过声明固定大小的结构来处理,而不是包含实际字符串的结构,而是指向字符串的指针。

类似于:

UInt16 stringLength
char* zeroTerminatedString

在 C# 中是否有一种(聪明的)方法来做类似的事情?我的意思是从文件/内存加载二进制数据并将其填充到结构中?

问候雅各布·贾斯特森

最佳答案

这不是你在 C 中声明它的方式。如果文件中的记录包含一个字符串,那么你将声明类似于以下的结构:

struct Example {
int mumble; // Anything, not necessarily a string length
char text[42];
// etc...
};

等效的 C# 声明如下所示:

    [StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
private struct Example {
public int mumble;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 42)]
public string text;
// etc...
}

您通常会使用 BinaryReader 来读取数据。但它不能像这样直接处理字符串,你必须将它们作为 byte[] 读取并自己进行字符串转换。您也无法利用声明性语法,您必须为结构的每个单独成员编写一个调用。

有一个解决方法,Marshal 类已经知道如何使用 PtrToStructure() 方法将非托管结构转换为托管结构。这是一个通用实现,它适用于任何 blittable 类型。两个版本,一个从 byte[] 读取的静态版本和一个优化为从流中重复读取的实例方法。您可以将 FileStream 或 MemoryStream 与那个一起使用。

using System;
using System.IO;
using System.Runtime.InteropServices;

class StructTranslator {
public static bool Read<T>(byte[] buffer, int index, ref T retval) {
if (index == buffer.Length) return false;
int size = Marshal.SizeOf(typeof(T));
if (index + size > buffer.Length) throw new IndexOutOfRangeException();
var handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
try {
IntPtr addr = (IntPtr)((long)handle.AddrOfPinnedObject() + index);
retval = (T)Marshal.PtrToStructure(addr, typeof(T));
}
finally {
handle.Free();
}
return true;
}

public bool Read<T>(Stream stream, ref T retval) {
int size = Marshal.SizeOf(typeof(T));
if (buffer == null || size > buffer.Length) buffer = new byte[size];
int len = stream.Read(buffer, 0, size);
if (len == 0) return false;
if (len != size) throw new EndOfStreamException();
var handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
try {
retval = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
}
finally {
handle.Free();
}
return true;
}

private byte[] buffer;
}

未经测试,希望它有效。

关于c# - 将二进制数据加载到结构中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58084869/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com