C# 访问二维固定字节数组

C# 访问二维固定字节数组,c#,pascal,C#,Pascal,我正在努力使用二维固定字节数组。我必须转换一个大小与C相似的pascal字符类型。我必须在这个数组中有一些字符值 我将其声明为公共固定字节C10VAFT[14*20] 我不知道这个数组是一个大小为280的一维数组,还是一个二维数组,原因是我无法得到我的内涵值,因为我得到的是一系列字节 谢谢 阿肖克 这是代码。 这是一个帕斯卡结构 CREC10 = RECORD C0RT : INTEGER; C0KEY1 : INTEGER; C10

我正在努力使用二维固定字节数组。我必须转换一个大小与C相似的pascal字符类型。我必须在这个数组中有一些字符值

我将其声明为公共固定字节C10VAFT[14*20]

我不知道这个数组是一个大小为280的一维数组,还是一个二维数组,原因是我无法得到我的内涵值,因为我得到的是一系列字节

谢谢 阿肖克

这是代码。 这是一个帕斯卡结构

CREC10 = RECORD
         C0RT    : INTEGER;
         C0KEY1  : INTEGER;
         C10VAFT : ARRAY [0..13] OF PACKED ARRAY [0..19] OF CHAR;
         C10VH1H : PACKED ARRAY [0..19] OF CHAR;
         C10VH2H : PACKED ARRAY [0..19] OF CHAR;
         C10VH3H : PACKED ARRAY [0..19] OF CHAR;
         C10MPE1 : PACKED ARRAY [0..14] OF CHAR;
         C10MPE2 : PACKED ARRAY [0..14] OF CHAR;
         C10MPE3 : PACKED ARRAY [0..14] OF CHAR;
         C10MPR1 : PACKED ARRAY [0..14] OF CHAR;
         C10MPR2 : PACKED ARRAY [0..14] OF CHAR;
         C10MPR3 : PACKED ARRAY [0..14] OF CHAR;
         SPARE2  : PACKED ARRAY [0..61] OF CHAR;
         C10CP   : INTEGER[4];
         C0BRRP  : INTEGER[8];
         END;
blow是C中的副本结构。我一直使用**元素

public unsafe struct CREC10
    {
        public short C0RT;                     
        public short C0KEY1;
        **public fixed byte C10VAFT[14*20];**
        public fixed byte C10VH1H[20];
        public fixed byte C10VH2H[20];
        public fixed byte C10VH3H[20];
        public fixed byte C10MPE1[15];
        public fixed byte C10MPE2[15];
        public fixed byte C10MPE3[15];
        public fixed byte SPARE2[62];
        public UcsdInt4 C0CP;
        public UcsdInt4 C0BRRP;

    }

通过使用此十进制C10VAFT[14*20],您将获得一个3920的数组,您将获得一个字节数组,因为.net中字符和字节之间的区别是 字节=8位,字符=2字节16位,这与PASCAL不同,PASCAL中的字节和字符是相同的

在C语言中,多维数组是这样声明的

 char[,] array = new char[14, 20]


通过使用此十进制C10VAFT[14*20],您将获得一个3920的数组,您将获得一个字节数组,因为.net中字符和字节之间的区别是 字节=8位,字符=2字节16位,这与PASCAL不同,PASCAL中的字节和字符是相同的

在C语言中,多维数组是这样声明的

 char[,] array = new char[14, 20]


对于您的问题,本机的答案是无法生成二维固定数组。编译器不允许您这样做。报告说:

不安全的缓冲区总是向量或一维数组

如果要继续使用“不安全”和“固定”,则需要:

声明14个独立的固定字节数组。 声明一个长度为14*20的单固定字节数组,然后手动索引到该数组中。 索引将如下所示:

int arrIndex(int elementIndex, int charIndex)
{
    return (elementIndex*20) + charIndex;
}
    public static CREC10 FromStream(Stream stream)
    {
        CREC10 result;
        using (BinaryReader reader = new BinaryReader(stream))
        {
            result.C0RT = reader.ReadInt32();
            result.C0KEY1 = reader.ReadInt32();
            result.C10VAFT = new string[14];
            for (int i=0; i<result.C10VAFT.Length; i++)
            {
                result.C10VAFT[i] = Encoding.ASCII.GetString(reader.ReadBytes(20));
            }
            result.C10VH1H = Encoding.ASCII.GetString(reader.ReadBytes(20));
        }
        return result;
    }
这确实说明了使用固定大小缓冲区必须跨越的语法障碍

我认为您实际上正在做的是根据您的Pascal记录获取一个字节流,并希望将其转换为C结构。可能还会回来。在我看来,尝试在C中使用相同的布局是错误的。编译器不希望您这样做。不要反抗。对结构使用自然C布局,并提供自然C布局和磁盘布局之间的映射

我想说的第一点是,你绝对不需要也不想在这里使用不安全的或固定的。这两种情况都会让你的生活变得更加艰难

首先,我将假设您的原始数据位于C流实例中。如果它来自字节流,则您将生成一个MemoryStream:

但这并不重要。它可以是一个文件流。它只想待在小溪里

然后定义一个C结构来接收数据。这不需要匹配Pascal数据结构的严格布局。使用本机C类型。例如:

public struct CREC10
{
    public int C0RT;
    public int C0KEY1;
    public string[] C10VAFT;
    public string C10VH1H;

    public static CREC10 FromStream(Stream stream)
    {
        ....
    }
}
我还没有定义所有字段。刚好够让你尝一尝。我还添加了一个静态方法,可以从流中创建一个新方法。这将按如下方式实施:

int arrIndex(int elementIndex, int charIndex)
{
    return (elementIndex*20) + charIndex;
}
    public static CREC10 FromStream(Stream stream)
    {
        CREC10 result;
        using (BinaryReader reader = new BinaryReader(stream))
        {
            result.C0RT = reader.ReadInt32();
            result.C0KEY1 = reader.ReadInt32();
            result.C10VAFT = new string[14];
            for (int i=0; i<result.C10VAFT.Length; i++)
            {
                result.C10VAFT[i] = Encoding.ASCII.GetString(reader.ReadBytes(20));
            }
            result.C10VH1H = Encoding.ASCII.GetString(reader.ReadBytes(20));
        }
        return result;
    }
这确实假设您的结构中没有包装。看起来情况确实如此。我还假设你的整数是4字节宽,但对于这个有点老的Pascal编译器来说,情况可能不是这样。无论如何,我相信您知道数据结构的二进制布局,并且能够解决这些细节

您可以编写一个匹配函数,以使用相同的格式将结构复制到流中


如果你试图坚持用C语言编写严格的Pascal布局,你会发现用C代码实际处理数据是极其困难的。

你的问题的自然答案是你无法制作二维固定数组。编译器不允许您这样做。报告说:

不安全的缓冲区总是向量或一维数组

如果要继续使用“不安全”和“固定”,则需要:

声明14个独立的固定字节数组。 声明一个长度为14*20的单固定字节数组,然后手动索引到该数组中。 索引将如下所示:

int arrIndex(int elementIndex, int charIndex)
{
    return (elementIndex*20) + charIndex;
}
    public static CREC10 FromStream(Stream stream)
    {
        CREC10 result;
        using (BinaryReader reader = new BinaryReader(stream))
        {
            result.C0RT = reader.ReadInt32();
            result.C0KEY1 = reader.ReadInt32();
            result.C10VAFT = new string[14];
            for (int i=0; i<result.C10VAFT.Length; i++)
            {
                result.C10VAFT[i] = Encoding.ASCII.GetString(reader.ReadBytes(20));
            }
            result.C10VH1H = Encoding.ASCII.GetString(reader.ReadBytes(20));
        }
        return result;
    }
这确实说明了使用固定大小缓冲区必须跨越的语法障碍

我认为您实际上正在做的是根据您的Pascal记录获取一个字节流,并希望将其转换为C结构。可能还会回来。在我看来,尝试在C中使用相同的布局是错误的。编译器不希望您这样做。不要反抗。对结构使用自然C布局,并提供自然C布局和磁盘布局之间的映射

我想说的第一点是,你绝对不需要也不想在这里使用不安全的或固定的。这两种情况都会让你的生活变得更加艰难

首先,我将假设您的原始数据位于C流实例中。如果是 来自字节流,然后您将生成一个MemoryStream:

但这并不重要。它可以是一个文件流。它只想待在小溪里

然后定义一个C结构来接收数据。这不需要匹配Pascal数据结构的严格布局。使用本机C类型。例如:

public struct CREC10
{
    public int C0RT;
    public int C0KEY1;
    public string[] C10VAFT;
    public string C10VH1H;

    public static CREC10 FromStream(Stream stream)
    {
        ....
    }
}
我还没有定义所有字段。刚好够让你尝一尝。我还添加了一个静态方法,可以从流中创建一个新方法。这将按如下方式实施:

int arrIndex(int elementIndex, int charIndex)
{
    return (elementIndex*20) + charIndex;
}
    public static CREC10 FromStream(Stream stream)
    {
        CREC10 result;
        using (BinaryReader reader = new BinaryReader(stream))
        {
            result.C0RT = reader.ReadInt32();
            result.C0KEY1 = reader.ReadInt32();
            result.C10VAFT = new string[14];
            for (int i=0; i<result.C10VAFT.Length; i++)
            {
                result.C10VAFT[i] = Encoding.ASCII.GetString(reader.ReadBytes(20));
            }
            result.C10VH1H = Encoding.ASCII.GetString(reader.ReadBytes(20));
        }
        return result;
    }
这确实假设您的结构中没有包装。看起来情况确实如此。我还假设你的整数是4字节宽,但对于这个有点老的Pascal编译器来说,情况可能不是这样。无论如何,我相信您知道数据结构的二进制布局,并且能够解决这些细节

您可以编写一个匹配函数,以使用相同的格式将结构复制到流中



如果您试图坚持使用C语言的严格Pascal布局,您将发现用C代码实际处理数据非常困难。

您也可以使用char[,]array=new char[int size,int size]声明您显示的不是多维数组。它被称为锯齿阵列,两者都是不同的。对不起,我更新了我的答案,但它会起作用either@JulieShannon具体地说,我必须阅读一些UCSD pascal.DTA,其中一个类似的结构具有大小为[14][20]的2D数组在C语言中,我必须有一个类似内存大小的数组,这可能是采用固定字节2D数组的可能。因此,这就是我被击中的地方。希望这次我完全解决了我的问题:这里的Char是错误的。这些肯定是字节。您没有讨论fixed的用法,这是您的疏忽。您还可以使用char[,]array=new char[int size,int size]声明您显示的不是多维数组。它被称为锯齿阵列,两者都是不同的。对不起,我更新了我的答案,但它会起作用either@JulieShannon具体地说,我必须阅读一些UCSD pascal.DTA,其中一个类似的结构具有大小为[14][20]的2D数组在C语言中,我必须有一个类似内存大小的数组,这可能是采用固定字节2D数组的可能。因此,这就是我被击中的地方。希望这次我完全解决了我的问题:这里的Char是错误的。这些肯定是字节。你没有讨论fixed的使用是失职的。你能添加一些到目前为止的代码吗?我很想帮你,但你还没有问一个真正的问题。您没有显示pascal数据结构,也没有描述如何使用它。@DavidHeffernan我已经添加了该结构。请详细说明如何使用它。首先,我必须说,我确信你不需要不安全的或固定的。您正在尝试对DLL进行pinvoke吗?事实上,pascal中的2d字符数组具有字符串类型的值,需要在C中从DTA文件中检索这些值,在对这些值进行更改后,必须将其保存回.DTA文件。我的目的是获取特定索引的字节流,然后将这些字节转换为字符串,但我无法获取这些字节,这就是问题所在,你能添加一些到目前为止的代码吗?我很想提供帮助,但你还没有问过真正的问题。您没有显示pascal数据结构,也没有描述如何使用它。@DavidHeffernan我已经添加了该结构。请详细说明如何使用它。首先,我必须说,我确信你不需要不安全的或固定的。您正在尝试对DLL进行pinvoke吗?事实上,pascal中的2d字符数组具有字符串类型的值,需要在C中从DTA文件中检索这些值,在对这些值进行更改后,必须将其保存回.DTA文件。我的目的是获取特定索引的字节流,然后将这些字节转换为字符串,但我无法获取这些字节,这就是问题所在,但此结构将超过512字节大小的限制,在这种情况下,从数据库读取的数据将不合适,因为我通过DLL从固定函数接口读取数据。@user3079498内存中的表示不需要与磁盘上的表示相匹配。如果您强制数据以与传统Pascal结构相同的布局保存在C中,您将发现处理数据非常困难。@user3079498现在我的答案告诉您不能使用2D固定缓冲区。我仍然相信你的方法是错误的,但是如果你想坚持下去,我的答案会告诉你如何去做。我认为我们缺少的是对为什么你觉得有必要在你的C代码中匹配二进制布局的一些理解。我怀疑你只是在没有充分了解后果的情况下决定了这一点。固定大小的缓冲区完全是一场噩梦。但是,也许有一个很好的理由说明您需要匹配二进制布局。如果是这样,请告诉我们。我的意思是,我回答的第一部分肯定回答了你提出的直接问题。我们可以到此为止,但我认为我们可以做得更好。我想确保你得到最好的解决方案。我真的很喜欢这个应用程序
我感谢你在这件事上的帮助。谢谢。关于我对使用固定缓冲区的理解,你说得很对,但我坚持使用固定缓冲区,因为我的遗留系统和现有代码仅以这种方式处理。。所以我必须这样做,但这个结构将超过512字节大小的限制,在这种情况下,从数据库读取的数据将不合适,因为我通过DLL从固定函数接口读取数据。@user3079498内存中的表示不需要与磁盘上的表示相匹配。如果您强制数据以与传统Pascal结构相同的布局保存在C中,您将发现处理数据非常困难。@user3079498现在我的答案告诉您不能使用2D固定缓冲区。我仍然相信你的方法是错误的,但是如果你想坚持下去,我的答案会告诉你如何去做。我认为我们缺少的是对为什么你觉得有必要在你的C代码中匹配二进制布局的一些理解。我怀疑你只是在没有充分了解后果的情况下决定了这一点。固定大小的缓冲区完全是一场噩梦。但是,也许有一个很好的理由说明您需要匹配二进制布局。如果是这样,请告诉我们。我的意思是,我回答的第一部分肯定回答了你提出的直接问题。我们可以到此为止,但我认为我们可以做得更好。我想确保你得到最好的解决方案。我真的很感谢你在这件事上的帮助。谢谢。关于我对使用固定缓冲区的理解,你说得很对,但我坚持使用固定缓冲区,因为我的遗留系统和现有代码仅以这种方式处理。。所以我一定要这么做