2017-04-05 1 views
1

binaryformatter를 사용하여 개체를 serialize 할 때 작은 걸림이 발생했습니다. 직렬화의 요점은 바이트 배열이 필요한 해시 함수에 값을 전달할 수 있기 때문입니다.C# 이진 포매터 속성의 값이 같음

내가 가진 프로세스는 newtonsoft Jsonconvert를 사용하여 json 파일을 POCO 개체로 만들고, 몇 가지 검사를 수행하고, 필요에 따라 값을 업데이트하고, Json 형식으로 동일한 파일에 다시 저장하는 프로세스입니다.

해시 값이 파일에서 프로세스 시작시 재생성 된 내용과 일치하는지 확인하는 작업이 포함됩니다. 내가 취한 단계는 파일을 읽고, POCO로 변환하고, 바이너리 포맷터를 사용하여 직렬화하고, 해시 값을 생성하고, 올바른 경우 두 값을 비교하고, 데이터를 업데이트하고 파일에 Json으로 새 해시 값과 객체를 저장하는 단계입니다.

그러나 바이너리 포맷터를 사용하여 객체를 직렬화 할 때 걸린 부분이 있습니다. 객체의 값이 같은 속성이있는 경우 직렬화 기의 바이트 출력은 파일에서 데이터를 읽을 때와 다르게 출력됩니다. 바이트 배열의 값이 다르기 때문에 해시 값도 다릅니다. 또한 속성 값이 다른 경우 동일한 해시 값이 생성되므로 아무런 문제도 발생하지 않습니다.

내 질문에 왜 개체가 읽고 파일에 쓸 때 다른 값을 바이트 값을 발생시키는 이유입니다.

[Serializable] 
public class UserAuthorisationData 
{ 
    public string surname { get; set; } 
    public string forename { get; set; } 
    public string initials { get; set; } 

    public UserAuthorisationData() 
    { 
     surname = ""; 
     forename = ""; 
     initials = ""; 

    } 
} 

위의 예에서
var objectA = new UserAuthorisationData() 
objectA.surname = "Fred"; 
objectA.forename = "John"; 
objectA.initials = "FJ"; 

var objectB = new UserAuthorisationData() 
objectB.surname = "John"; 
objectB.forename = "John"; 
objectB.initials = "JJ"; 

를, 해시 값이 파일 인 경우 데이터가 기입 될 때와 동안 모두 생성되면 objectA의 바이트 배열의 값이 같다 다시 읽습니다.

그러나 objectB의 경우 값이 다릅니다. 아래

방법은 바이트로 개체를 변환 :

protected virtual byte[] ObjectToByteArray(object objectToSerialize) 
    { 
     BinaryFormatter formatter = new BinaryFormatter(); 
     MemoryStream fs = new MemoryStream(); 

     try 
     { 

      lock (locker) 
      {     
       formatter.Serialize(fs, objectToSerialize); 
       Logger.Debug($"Successfully converted object to bytes for serialization."); 
      } 
      File.WriteAllBytes(@"C:\ali.kamal\User1.txt", fs.ToArray()); 

      return fs.ToArray(); 
     } 
    } 

호출 방법을 객체

ObjectToByteArray(objectA); 
ObjectToByteArray(objectB); 

업데이트 1

감사 하디에. 해시 코드는 Microsoft의 HMACSHA256.computeHash 메서드를 사용하여 생성됩니다.

protected override string ComputeHash(byte[] objectAsBytes, byte[] key) 
    { 
     byte[] hashValue = null; 
     try 
     { 
      using (HMACSHA256 hmac = new HMACSHA256(key)) 
      { 
       hashValue = hmac.ComputeHash(objectAsBytes); 

      } 
     }catch(Exception ex) 
     { 
      EventLogger.LogEvent($"Could not generate SHA256 hash value, exception:{ex.Message}", EventEntryType.Error); 
     } 

     return Convert.ToBase64String(hashValue); 
    } 

string hashvalue = ComputeHash(ObjectToByteArray(objectA), ObjectToByteArray("abcd")) 

답변

0

나는 다른 방법보다는 해시 코드 메소드의 바이트 비교할 수 제안 : Array1.SequenceEqual(Array2)를, 그것의하지 당신은 귀하의 질문에 두 배열의 해시 코드를 비교하는,하지만 난 당신이 가정하는 방법을 명확 GetHashCode 메서드를 사용 중입니다. Array1.GetHashCode() == Array2.GetHashCode()을 사용하면 HasCode 함수를 재정의하지 않는 한 사용자의 경우에 적합하지 않습니다. 다음은 작업 Demo

희망

using System; 
using System.IO; 
using System.Linq; 
using System.Runtime.Serialization.Formatters.Binary; 

namespace ConsoleApp1 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      var a = new UserData(); 
      var b = new UserData(); 

      var aS = ObjectToByte(a); 
      var bS = ObjectToByte(b); 
      Console.WriteLine("A : {0}", a); 
      Console.WriteLine("B : {0}", b); 
      // result for empty objects are equal 
      Console.WriteLine("A == B ? => {0} \n\n", aS.SequenceEqual(bS)); 

      a = new UserData() 
      { 
       ForeName = "A", 
       Initials = "CC", 
       SurName = "B", 
      }; 

      b = new UserData() 
      { 
       ForeName = "AX", 
       Initials = "CC", 
       SurName = "B", 
      }; 

      aS = ObjectToByte(a); 
      bS = ObjectToByte(b); 

      Console.WriteLine("A : {0}", a); 
      Console.WriteLine("B : {0}", b); 
      // result for same data type with same object values are equal 
      Console.WriteLine("A == B ? => {0} \n\n", aS.SequenceEqual(bS)); 

      a = new UserData() 
      { 
       ForeName = "AX", 
       Initials = "CC", 
       SurName = "B", 
      }; 
      b = a; 

      aS = ObjectToByte(a); 
      bS = ObjectToByte(b); 

      Console.WriteLine("A : {0}", a); 
      Console.WriteLine("B : {0}", b); 
      // result for different objects are not equal 
      Console.WriteLine("A == B ? => {0} \n\n", aS.SequenceEqual(bS)); 
     } 

     static byte[] ObjectToByte(object item) 
     { 
      var formatter = new BinaryFormatter(); 
      using (var memory = new MemoryStream()) 
      { 
       formatter.Serialize(memory, item); 
       return memory.ToArray(); 
      } 
     } 
    } 

    [Serializable] 
    public class UserData 
    { 
     public string SurName { get; set; } 
     public string ForeName { get; set; } 
     public string Initials { get; set; } 

     public override string ToString() 
     { 
      return string.Format("{{SurName: {0} , ForeName:{1}, Initials:{2}}}", SurName ?? "Empty", ForeName ?? "Empty", Initials ?? "Empty"); 
     } 
    } 
} 

이 당신에게

+0

감사 하디 도움이 될 것입니다 : 아래하여 SequenceEqual 방법을 사용하는 콘솔 응용 프로그램을 사용하여 샘플입니다.해시 코드는 Microsoft의 HMACSHA256.computeHash를 사용하여 생성됩니다. –

+0

동일한'HMACSHA256'객체를 사용하는 한 동일한 결과를주었습니다.'var h = new HMACSH256(); var aS = h.ComputeHash (ObjectToByte (a)); var bS = h.ComputeHash (ObjectToByte (b));'지금은'bS.SequenceEqual (aS)'가 제대로 작동하지만, 다른 HMACSH256으로 개체를 계산하면 작동하지 않습니다. – Monah

+0

좋아요. 그러나 바이트 배열의 값이 다른 이유는 알고 있습니다. –