Я пытаюсь сериализовать структуру на диск как необработанные байты. Это (упрощенная) версия.
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public class TestData :BaseStructure
{
public byte[] bytes = new byte[]{65,66,67}; // this doesn't write ABC as expected
}
Функция write
использует метод ConvertStructureToBytes
для преобразования этого массива в байтовый массив, а затем его записывает двоичный модуль записи.
public void Write(BaseStructure baseStructure)
{
binaryWriter.Write(ConvertStructureToBytes(baseStructure));
}
Раздел ConvertStructureToBytes
public byte[] ConvertStructureToBytes(BaseStructure baseStructure)
{
int len = Marshal.SizeOf(baseStructure);
byte[] arr = new byte[len];
IntPtr ptr = Marshal.AllocHGlobal(len);
Marshal.StructureToPtr(baseStructure, ptr,false);
Marshal.Copy(ptr, arr, 0, len);
Marshal.FreeHGlobal(ptr);
return arr;
}
Если я заменю строку байтов на
public byte byte = 65; // This now writes an A , as expected
Я пытался
public byte[] bytes = Encoding.ASCII.GetBytes("ABC"); //doesn't work either
Вероятно, это как-то связано с функцией ConvertStructureToBytes
, она не обрабатывает байтовый массив должным образом.
Что мне нужно сделать, чтобы успешно написать «ABC»?
3 ответа
Несколько проблем. Сначала ваше объявление структуры неверно, вы должны встроить массив, чтобы он больше не был указателем:
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public class TestData {
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public byte[] bytes = new byte[] { 65, 66, 67 };
}
Тогда ваш метод ConvertStructureToBytes () неверен, он будет только маршалировать BaseStructure. Вам нужно сделать его универсальным:
public static byte[] ConvertStructureToBytes<T>(T baseStructure) {
// rest the same...
}
Обратите внимание на проблемы, с которыми вы можете столкнуться с этим подходом, это, безусловно, не универсальный способ маршалинга данных. Таким образом можно сериализовать только очень конкретные классы. Этот атрибут [MarshalAs], конечно, очень болезненно поддерживать. Вы также можете использовать двоичную сериализацию.
Измените определение класса на это и попробуйте:
StructLayout(LayoutKind.Sequential, Pack = 1)]
public class TestData :BaseStructure
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public byte[] bytes = new byte[]{65,66,67};
}
Попробуй это:
byte[] bytes = Encoding.ASCII.GetBytes("ABC").ToArray();
Или после того, как я это проверил. Может вы имеете в виду это:
bytes = new byte[] { 65, 66, 67 };
string test = Encoding.UTF8.GetString(bytes).ToString();
Похожие вопросы
Новые вопросы
c#
C# (произносится как «see Sharp») — это высокоуровневый мультипарадигменный язык программирования со статической типизацией, разработанный Microsoft. Код C# обычно нацелен на семейство инструментов и сред выполнения Microsoft .NET, которое включает в себя .NET, .NET Framework, .NET MAUI и Xamarin среди прочих. Используйте этот тег для ответов на вопросы о коде, написанном на C#, или о формальной спецификации C#.
BaseStructure
? Ваш классTestData
наследуется от него, но вы сериализуете не экземплярTestData
, а экземплярBaseStructure
, который не знает о данных, объявленных в классеTestData
.