2016-12-15 210 views
1

我有以下C#代碼將我的數組數組轉換爲字節數組,然後將其保存爲base64字符串,反之亦然,但它不適用於因爲是8字節,我的代碼僅適用於4字節數字。將數組數組轉換爲字節,反之亦然C#

private static int _endianDiff1; 
private static int _endianDiff2; 
private static int _idx; 
private static byte[] _byteBlock; 

enum ArrayType { Float, Int32, UInt32, Int64, UInt64 } 

public static bool SetIntArray(string key, int[] intArray) 
{ 
    return SetValue(key, intArray, ArrayType.Int32, 1, ConvertFromInt); 
} 

public static bool SetLongArray(string key, long[] longArray) 
{ 
    return SetValue(key, longArray, ArrayType.Int64, 1, ConvertFromLong); 
} 

private static bool SetValue<T>(string key, T array, ArrayType arrayType, int vectorNumber, Action<T, byte[], int> convert) where T : IList 
{ 
    var bytes = new byte[(4 * array.Count) * vectorNumber + 1]; 
    bytes[0] = Convert.ToByte(arrayType); // Identifier 
    Initialize(); 

    for (var i = 0; i < array.Count; i++) 
    { 
     convert(array, bytes, i); 
    } 
    return SaveBytes(key, bytes); 
} 

private static void ConvertFromInt(int[] array, byte[] bytes, int i) 
{ 
    ConvertInt32ToBytes(array[i], bytes); 
} 

private static void ConvertFromLong(long[] array, byte[] bytes, int i) 
{ 
    ConvertInt64ToBytes(array[i], bytes); 
} 

public static int[] GetIntArray(string key) 
{ 
    var intList = new List<int>(); 
    GetValue(key, intList, ArrayType.Int32, 1, ConvertToInt); 
    return intList.ToArray(); 
} 

public static long[] GetLongArray(string key) 
{ 
    var longList = new List<long>(); 
    GetValue(key, longList, ArrayType.Int64, 1, ConvertToLong); 
    return longList.ToArray(); 
} 

private static void GetValue<T>(string key, T list, ArrayType arrayType, int vectorNumber, Action<T, byte[]> convert) where T : IList 
{ 
    if (!PlayerPrefs.HasKey(key)) 
     return; 
    var bytes = Convert.FromBase64String(PlayerPrefs.GetString(key)); 
    if ((bytes.Length - 1) % (vectorNumber * 4) != 0) 
    { 
     Debug.LogError("Corrupt preference file for " + key); 
     return; 
    } 
    if ((ArrayType)bytes[0] != arrayType) 
    { 
     Debug.LogError(key + " is not a " + arrayType + " array"); 
     return; 
    } 
    Initialize(); 

    var end = (bytes.Length - 1)/(vectorNumber * 4); 
    for (var i = 0; i < end; i++) 
    { 
     convert(list, bytes); 
    } 
} 

private static void ConvertToInt(List<int> list, byte[] bytes) 
{ 
    list.Add(ConvertBytesToInt32(bytes)); 
} 

private static void ConvertToLong(List<long> list, byte[] bytes) 
{ 
    list.Add(ConvertBytesToInt64(bytes)); 
} 

private static void Initialize() 
{ 
    if (BitConverter.IsLittleEndian) 
    { 
     _endianDiff1 = 0; 
     _endianDiff2 = 0; 
    } 
    else 
    { 
     _endianDiff1 = 3; 
     _endianDiff2 = 1; 
    } 
    if (_byteBlock == null) 
    { 
     _byteBlock = new byte[4]; 
    } 
    _idx = 1; 
} 

private static bool SaveBytes(string key, byte[] bytes) 
{ 
    try 
    { 
     PlayerPrefs.SetString(key, Convert.ToBase64String(bytes)); 
    } 
    catch 
    { 
     return false; 
    } 
    return true; 
} 

private static void ConvertInt32ToBytes(int i, byte[] bytes) 
{ 
    _byteBlock = BitConverter.GetBytes(i); 
    ConvertTo4Bytes(bytes); 
} 

private static void ConvertInt64ToBytes(long i, byte[] bytes) 
{ 
    _byteBlock = BitConverter.GetBytes(i); 
    ConvertTo8Bytes(bytes); 
} 

private static int ConvertBytesToInt32(byte[] bytes) 
{ 
    ConvertFrom4Bytes(bytes); 
    return BitConverter.ToInt32(_byteBlock, 0); 
} 

private static long ConvertBytesToInt64(byte[] bytes) 
{ 
    ConvertFrom8Bytes(bytes); 
    return BitConverter.ToInt64(_byteBlock, 0); 
} 

private static void ConvertTo4Bytes(byte[] bytes) 
{ 
    bytes[_idx] = _byteBlock[_endianDiff1]; 
    bytes[_idx + 1] = _byteBlock[1 + _endianDiff2]; 
    bytes[_idx + 2] = _byteBlock[2 - _endianDiff2]; 
    bytes[_idx + 3] = _byteBlock[3 - _endianDiff1]; 
    _idx += 4; 
} 

private static void ConvertFrom4Bytes(byte[] bytes) 
{ 
    _byteBlock[_endianDiff1] = bytes[_idx]; 
    _byteBlock[1 + _endianDiff2] = bytes[_idx + 1]; 
    _byteBlock[2 - _endianDiff2] = bytes[_idx + 2]; 
    _byteBlock[3 - _endianDiff1] = bytes[_idx + 3]; 
    _idx += 4; 
} 

private static void ConvertTo8Bytes(byte[] bytes) 
{ 

} 

private static void ConvertFrom8Bytes(byte[] bytes) 
{ 

} 

到目前爲止,我有工作了INTUINT浮動因爲他們都是4字節和我的問題是這樣它的工作原理基礎上,通過型式尺寸改變我的初始化函數。

我想也應該有ConvertTo8BytesConvertFrom8Bytes功能,我不知道該怎麼做,因爲我設置_endianDiff_byteBlock只有4個字節。我知道_byteBlock應該有動態大小而不是4,但我不知道在這種情況下如何處理字節序。

在側面說明,我已經通過拆分到2個INT S和剛剛將其存儲爲兩個INT陣列解決了這個問題,但我沒用分配內存喜歡這個只是因爲我不能使這個算法工作。

+0

在[BitConverter類](https://msdn.microsoft.com/en-us/library/system.bitconverter(v = vs.110).aspx)上採取一些措施。 – Abion47

+0

'string ConvertToBase64(IEnumerable list) { var bytes = list.Select(x => BitConverter.GetBytes(x))。SelectMany(x => x).ToArray(); return Convert.ToBase64String(bytes); }' –

回答

3

好像很多代碼,如果你正在做的是試圖獲得數值數組的Base64表示。我錯過了目標嗎?

如果你想要做的就是int或長數組和字符串的base64,試試這個:

private static string ConvertArrayToBase64<T>(IList<T> array) where T : struct 
    { 
     if (typeof(T).IsPrimitive) 
     { 
      int size = System.Runtime.InteropServices.Marshal.SizeOf<T>(); 
      var byteArray = new byte[array.Count * size]; 
      Buffer.BlockCopy(array.ToArray(), 0, byteArray, 0, byteArray.Length); 
      return Convert.ToBase64String(byteArray); 
     } 
     throw new InvalidOperationException("Only primitive types are supported."); 
    } 

    private static T[] ConvertBase64ToArray<T>(string base64String) where T : struct 
    { 
     if (typeof(T).IsPrimitive) 
     { 
      var byteArray = Convert.FromBase64String(base64String); 
      var array = new T[byteArray.Length/System.Runtime.InteropServices.Marshal.SizeOf<T>()]; 
      Buffer.BlockCopy(byteArray, 0, array, 0, byteArray.Length); 
      return array; 
     } 
     throw new InvalidOperationException("Only primitive types are supported."); 
    } 

有幾件事情要考慮此代碼雖然...

它確實構成了數組的完整副本,所以如果您正在處理大型數組或性能敏感的操作,它可能不是最好的方法。

這應與任何「原始值類型」陣列,其中應包括所有的數字類型如int,長,UINT,float等

爲了證明使用工作,見下面的例子:

 var longArray = new long[] { 11111, 22222, 33333, 44444 }; 
     var intArray = new int[] { 55555, 66666, 77777, 88888}; 

     string base64longs = ConvertArrayToBase64(longArray); 
     Console.WriteLine(base64longs); 
     Console.WriteLine(string.Join(", ", ConvertBase64ToArray<long>(base64longs))); 

     string base64ints = ConvertArrayToBase64(intArray); 
     Console.WriteLine(base64ints); 
     Console.WriteLine(string.Join(", ", ConvertBase64ToArray<int>(base64ints))); 

做些什麼:

  • 驗證陣列只有原始類型。
  • 確定數組中元素的大小爲 計算要分配的字節數組的長度。
  • 它將陣列複製到字節數組。
  • 返回base64表示。

補充功能正好相反。

更新:這裏是.NET 2.0兼容版本...

private static string ConvertArrayToBase64<T>(IList<T> array) where T : struct 
    { 
     if (typeof(T).IsPrimitive) 
     { 
      int size = System.Runtime.InteropServices.Marshal.SizeOf(typeof(T)); 
      var byteArray = new byte[array.Count * size]; 
      Buffer.BlockCopy((Array)array, 0, byteArray, 0, byteArray.Length); 
      return Convert.ToBase64String(byteArray); 
     } 
     throw new InvalidOperationException("Only primitive types are supported."); 
    } 

    private static T[] ConvertBase64ToArray<T>(string base64String) where T : struct 
    { 
     if (typeof(T).IsPrimitive) 
     { 
      var byteArray = Convert.FromBase64String(base64String); 
      var array = new T[byteArray.Length/System.Runtime.InteropServices.Marshal.SizeOf(typeof(T))]; 
      Buffer.BlockCopy(byteArray, 0, array, 0, byteArray.Length); 
      return array; 
     } 
     throw new InvalidOperationException("Only primitive types are supported."); 
    } 
+0

此代碼不會爲我編譯*非泛型方法'Marshal.SizeOf(object)'不能與類型參數一起使用* –

+0

您正在使用Marshal.SizeOf(object)或Marshal.SizeOf () ?代碼示例使用後者,編譯並運行良好。它們是不同的功能。一個傳遞類型T作爲泛型類型,另一個傳遞一個對象來確定類型。你使用的是什麼版本的.NET? –

+0

我使用了示例中的代碼。我堅持使用.NET 2.0,因爲我使用Unity。 –

相關問題