2016-07-15 67 views
0

我試圖序列化任意數量的維度的多維數組。請注意,我指的是實際的多維數組(float [,]),而不是鋸齒數組(float [] [])。如何設置未知級別的多維System.Array中每個元素的值?

序列化每個維度的長度後,我可以很容易地使用foreach(var item in array)序列化每個元素。

但是,當反序列化我不能使用foreach,因爲我需要分配值。我知道我需要使用array.SetValue(object value,params int [] indices),但我無法圍繞如何設置循環來執行通常使用嵌套的for循環所做的操作爲每個維度。

+0

你關心命令,或者你只需​​要數組中的所有值? – user3185569

+0

是的,我需要讀取BinaryReader中的所有內容以獲取最初序列化完全相同的數組。 – SilentSin

+0

使用BinaryFormatter不是一個選項嗎? –

回答

1

首先,使用foreach循環將原始數組序列化。它會使陣列變平。

然後,在被序列化以同樣的方式讀出值(代碼是基於陣列的enumerator

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); 
+0

非常感謝謝謝。 while循環和IncArray方法正是我所需要的。我希望Buffer.BlockCopy也適用於具有常量大小(int,float等)的類型,但不適用於字符串或用戶定義的類。我會嘗試添加它作爲優化的某個時候,但現在我只是很高興,它的工作原理。 – SilentSin

相關問題