Исправлен sbyte[] в строке C#
Я пытаюсь получить строку из памяти, используя StrucLayout
а также FieldOffset
Но у меня много проблем с пониманием того, как byte
работает.
Вот мой код банкомата:
[StructLayout(LayoutKind.Explicit)]
public unsafe struct InfoDetails
{
[FieldOffset(0x14)]
public fixed sbyte Name[50];
public string getName
{
get
{
fixed (sbyte* namePtr = Name)
{
return new string(namePtr);
}
}
}
}
Этот код returns
: T
, Ожидаемый результат TEZ
,
Любые советы о том, почему я делаю это неправильно? Спасибо
3 ответа
Вы можете изменить подпись на:
[FieldOffset(0x14)]
public fixed char Name[25];
public string getName
{
get
{
fixed (char* namePtr = Name)
{
return new string(namePtr);
}
}
}
Обратите внимание, как я изменился sbyte
в char
и я вдвое уменьшил размер буфера (потому что sizeof(char)
== 2)
Или вы можете даже, более просто добавить один актерский состав к char*
:
fixed (sbyte* namePtr = Name)
{
return new string((char*)namePtr);
}
не меняя ничего другого.
У вас, похоже, проблема со строковым кодированием. Рассмотрим следующий тестовый код:
unsafe
{
InfoDetails d;
var encoding = Encoding.Unicode;
var stringBytes = encoding.GetBytes("TEZ");
for(int i=0; i<stringBytes.Length; i++) d.Name[i] = (sbyte)stringBytes[i];
Console.WriteLine(d.getName);
}
Вы действительно получите "T", но если вы измените кодировку на Encoding.ASCII
вы получите "TEZ", как и ожидалось.
Решение: вам нужно заранее знать кодировку информации и соответственно сгенерировать строку. Похоже, это Unicode, поэтому попробуйте сначала:
fixed (sbyte* namePtr = Name)
{
return new string(namePtr, 0, 50, Encoding.Unicode);
}
Спасибо всем за ваш ответ, они помогли мне найти рабочее решение. Я действительно не знаю, является ли это лучшим:
[StructLayout(LayoutKind.Explicit)]
public unsafe struct InfoDetails
{
[FieldOffset(0x14)]
public fixed byte Name[50];
public string test
{
get
{
List<byte> clearBytes = new List<byte>();
fixed (byte* namePtr = Name)
{
for (int i = 0; i < 50; i++)
{
if (namePtr[i] == 0x0 && namePtr[i + 1] == 0x0)
{
break;
}
clearBytes.Add(namePtr[i]);
}
if (clearBytes.Count() % 2 != 0)
{
clearBytes.Add(0x00);
}
return Encoding.Unicode.GetString(clearBytes.ToArray());
}
}
}
}
Большое спасибо!