如何在 C# 中将固定字节/字符 [100] 转换为托管字符 []?

Posted

技术标签:

【中文标题】如何在 C# 中将固定字节/字符 [100] 转换为托管字符 []?【英文标题】:How to convert fixed byte/char[100] to managed char[] in C#? 【发布时间】:2010-11-14 04:34:40 【问题描述】:

在 C# 中将固定字节或 char[100] 转换为托管 char[] 的最佳方法是什么?我最终不得不使用指针算法,我想知道是否有更简单的方法——比如 memcpy 或其他方法?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;

namespace StructTest


    [StructLayout(LayoutKind.Explicit)]
    unsafe struct OuterType
    
        private const int BUFFER_SIZE = 100;

        [FieldOffset(0)]
        private int transactionType;

        [FieldOffset(0)]
        private fixed byte writeBuffer[BUFFER_SIZE];

        public int TransactionType
        
            get  return transactionType; 
            set  transactionType = value; 
        

        public char[] WriteBuffer
        
            set
            
                char[] newBuffer = value;

                fixed (byte* b = writeBuffer)
                
                    byte* bptr = b;
                    for (int i = 0; i < newBuffer.Length; i++)
                    
                         *bptr++ = (byte) newBuffer[i];
                    
                
            

            get
            
                char[] newBuffer = new char[BUFFER_SIZE];

                fixed (byte* b = writeBuffer)
                
                    byte* bptr = b;
                    for (int i = 0; i < newBuffer.Length; i++)
                    
                        newBuffer[i] = (char) *bptr++;
                    
                

                return newBuffer;
            
        
    

    class Program
    
        static void Main(string[] args)
        
            OuterType t = new OuterType();
            t.WriteBuffer = "hello there".ToCharArray();
            System.Console.WriteLine(t.WriteBuffer);
        
    

【问题讨论】:

【参考方案1】:

您可以为此使用Marshal.Copy。请注意,它还为 byte[] 重载,这可能是更合适的数据类型。

【讨论】:

我更新了 WriteBuffer 属性以返回一个字节[],然后使用 Marshal.Copy。一开始它可能应该是 byte[]。【参考方案2】:

我不知道在固定变量上进行转换的更好方法。然而,使这更简单的一种方法是完全避免使用固定变量。而是使用普通的 C# 数组并将其标记为 UnmanagedType.ByValArray

[FieldOffset(0), MarshalAs(UnmanagedType.ByValArray, SizeConst = BUFFER_SIZE)]
private byte[] writeBuffer;

然后您可以使用简单的 LINQ 查询来转换数据。下面是完整的解决方案

[StructLayout(LayoutKind.Explicit)]
unsafe struct OuterType

    private const int BUFFER_SIZE = 100;

    [FieldOffset(0)]
    private int transactionType;

    [FieldOffset(0), MarshalAs(UnmanagedType.ByValArray, SizeConst = BUFFER_SIZE)]
    private byte[] writeBuffer;

    public int TransactionType
    
        get  return transactionType; 
        set  transactionType = value; 
    

    public char[] WriteBuffer
    
        set  writeBuffer = value.Cast<byte>().ToArray(); 
        get  return writeBuffer.Cast<char>().ToArray(); 
    

【讨论】:

我曾在 writeBuffer 上尝试过 UnmanagedType.ByValArray,但遇到如下运行时异常。对于您的示例,该异常不会发生吗?如果没有,你能告诉我为什么吗?未处理的异常:System.TypeLoadException:无法从程序集“StructTest,Version=1.0.0.0,Culture=neutral,PublicKeyToken=null”加载类型“StructTest.OuterType”,因为它包含偏移量 0 处的对象字段,该对象字段未正确对齐或重叠通过非对象字段。在 StructTest.Program.Main(String[] args) 我的限制是我需要我的结构是一个联合,这就是为什么我需要为每个结构设置 FieldOffset(0)。 我试过了,如果他们都有 FieldOffset(0),我会收到我之前评论过的异常。 是的,这可能行不通,因为 .NET 不允许使用引用类型进行联合。

以上是关于如何在 C# 中将固定字节/字符 [100] 转换为托管字符 []?的主要内容,如果未能解决你的问题,请参考以下文章

如何在C#中将字节转换为字符串[重复]

如何在 c# 中将字符串从 utf8 转换(音译)为 ASCII(单字节)?

在 C# 中将字符串转换为字节数组

在c#中将字符串转换为字节数组

如何在 C# 中将字节 [] 转换为日期时间?

如何在 C# 中将结构转换为字节数组?