我正在尝试序列化具有任意数量维度的多维数组。请注意,我指的是实际的多维数组(float[,]),而不是交错数组(float[][])。
序列化每个维度的长度后,我可以使用 foreach(数组中的 var 项)轻松序列化每个元素。
但是在反序列化时,我不能使用 foreach,因为我需要分配值。我知道我需要使用数组。SetValue(对象值,参数 int[] 索引),但我无法弄清楚如何设置一个循环来执行您通常对每个维度的嵌套 for 循环所做的事情。
首先,使用 foreach
循环序列化原始数组。它将展平阵列。
然后,以与序列化相同的方式读取值(代码基于数组的枚举器)
var original = new int[2,2,2] { { { 1, 2 }, { 3, 4} }, { { 5, 6 }, { 7, 8 } } };
var serialized = original.Cast<int>().ToArray();
var originalBounds = Enumerable.Range(0, original.Rank)
.Select(i => original.GetUpperBound(i) + 1).ToArray();
var empty = Array.CreateInstance(typeof(int), originalBounds);
var indices = new int[empty.Rank];
indices[indices.Length - 1]--;
var index = 0;
while (IncArray(empty, indices))
{
empty.SetValue(serialized[index++], indices);
}
private bool IncArray(Array array, int[] indices)
{
int rank = array.Rank;
indices[rank - 1]++;
for (int i = rank - 1; i >= 0; i--)
{
if (indices[i] > array.GetUpperBound(i))
{
if (i == 0)
{
return false;
}
for (int j = i; j < rank; j++)
{
indices[j] = 0;
}
indices[i - 1]++;
}
}
return true;
}
这种方法将允许您从流中读取值 - 您不需要像我一样创建serialized
数组。
另一种方法是使用 Buffer.BulkCopy
.在这里,您必须读取整个数组,至少读取字节,并计算需要复制的字节数。这样做的好处是可以避免前面方法中的所有装箱,并且更简单:
var bytes = new byte[...]; // read the entire byte array
var empty = Array.CreateInstance(typeof(int), originalBounds);
Buffer.BlockCopy(bytes, 0, empty, 0, bytes.Length);