将固定大小的缓冲区(字节数组)转换为字符串

时间:2014-01-02 06:19:22

标签: c# arrays string unsafe

我在SO和其他论坛上看过几个相关的主题,但是我的问题没有找到可行的答案。

这是我的代码:

[StructLayout(LayoutKind.Explicit, Size = 128)]
internal unsafe struct Frame
{
    [FieldOffset(0)]
    public fixed byte Bytes[128];

    [FieldOffset(0)]
    public long Low;

    [FieldOffset(128 - sizeof(long))]
    public long High;
}

unsafe private void button32_Click(object sender, EventArgs e)
{
    Frame frame;

    // ERROR: Error 15  You cannot use the fixed statement to take the address of an already fixed expression
    fixed (byte* ptr = frame.Bytes)
    {

    }

    // ERROR
    Console.Write(System.Text.Encoding.ASCII.GetString(frame.Bytes, 0, 128));
    frame.Low = 1234;
    //Console.Write(System.Text.Encoding.ASCII.GetString(frame.Bytes));
    frame.High = 5678;
    //Console.Write(System.Text.Encoding.ASCII.GetString(frame.Bytes));
}

4 个答案:

答案 0 :(得分:2)

static byte[] GetBytes(string str)
{
    byte[] bytes = new byte[str.Length * sizeof(char)];
    System.Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length);
    return bytes;
}

static string GetString(byte[] bytes)
{
    char[] chars = new char[bytes.Length / sizeof(char)];
    System.Buffer.BlockCopy(bytes, 0, chars, 0, bytes.Length);
    return new string(chars);
}


static byte[] StringToByteArray(string str, int length) 
{
    return Encoding.ASCII.GetBytes(str.PadRight(length, ' '));
}  

答案 1 :(得分:1)

我明白了。刚刚将struct包装到另一个类中以消除固定指针问题。这将在新类的内存框架内创建结构。然后将固定数组转换为byte []以消除GetString()问题。也许这有帮助吗?

namespace test
{
        [StructLayout(LayoutKind.Explicit, Size = 128)]
        internal unsafe struct Frame
        {
            [FieldOffset(0)]
            public fixed byte Bytes[128];

            [FieldOffset(0)]
            public long Low;

            [FieldOffset(128 - sizeof(long))]
            public long High;

        }

    internal class NewClass
    {
        public Frame FixedBytesArray;
    }

    internal class Program
    {
        static void Main(string[] args)
        {
            unsafe
            {
                NewClass NewType = new NewClass();
                NewType.FixedBytesArray.High = 12345;
                NewType.FixedBytesArray.Low = 6789;
                // ERROR: Error 15  You cannot use the fixed statement to take the address of an already fixed expression
                fixed (byte* ptr = NewType.FixedBytesArray.Bytes)
                {
                    byte[] bytes = new byte[128];
                    int index = 0;
                    for (byte* counter = ptr; *counter != 0; counter++)
                    {
                        bytes[index++] = *counter;
                    }


                    // ERROR
                    Console.Write(System.Text.Encoding.ASCII.GetString(bytes, 0, 128));
                    //frame.Low = 1234;
                    //Console.Write(System.Text.Encoding.ASCII.GetString(frame.Low));
                    //frame.High = 5678;
                    //Console.Write(System.Text.Encoding.ASCII.GetString(frame.Bytes));
                }
            }

        }
    }
}

答案 2 :(得分:0)

编译器错误很好地说明了这一点:你试图修复已经修复过的东西......

您只在分配指针时修复引用。这可以防止将引用移动到内存中的其他位置(垃圾收集)然后预期 - 使用MS字,引用变为“固定”。

在你的情况下,你不需要在定义时修改你的结构,但是当引用你的指针时通过应用“fixed”语句来修复'source'(这部分代码是正确的)。

解决方案应该是从结构中删除fix语句。 如果您想阅读一些有关它的内容:MSDN - fixed Statement (C# Reference)

答案 3 :(得分:0)

以上内容对我无用,因此我创建了另一个解决方案:

StringBuilder sb = new StringBuilder();
fixed (byte* b = fixedByteArray)
{
  for (int i = 0; i < knownLengthOfByteArray; i++)
  {
    sb.Append((char)b[i]);
  }
}
return sb.ToString();

适用于ANSI字符串。