2017-05-10 20 views
-1

固定の形式で格納された異なる型の値を含むバイト配列を解析しています。たとえば、最初の4バイトは配列のサイズを含むintである可能性があります。 - 2倍の配列を考えて、次の8バイトはdoubleを表します。配列の最初の要素などです。理論的には他の型の値もあります。 bool、int、uint、short、ushort、long、ulong、float、double、およびこれらのそれぞれの配列のみを持つことができます。簡単なアプローチ:バイト配列からデシリアライズを一般化する

public class FixedFormatParser 
{ 
    private byte[] _Contents; 
    private int _CurrentPos = 0; 
    public FixedFormatParser(byte[] contents) 
    { 
     _Contents = contents; 
    } 

    bool ReadBool() 
    { 
     bool res = BitConverter.ToBoolean(_Contents, _CurrentPos); 
     _CurrentPos += sizeof(bool); 
     return res; 
    } 

    int ReadInt() 
    { 
     int res = BitConverter.ToInt32(_Contents, _CurrentPos); 
     _CurrentPos += sizeof(int); 
     return res; 
    } 

    // etc. for uint, short, ushort, long, ulong, float, double 

    int[] ReadIntArray() 
    { 
     int size = ReadInt(); 

     if (size == 0) 
      return null; 

     int[] res = new int[size]; 

     for (int i = 0; i < size; i++) 
      res[i] = ReadInt(); 

     return res; 
    } 

    // etc. for bool, uint, short, ushort, long, ulong, float, double 
} 

私は明らかに各ケースをカバーする18の方法を書くことができますが、これを一般化する方法があるように思われます。

bool val = Read<bool>(); 
long[] arr = ReadArray<long>(); // or ReadArray(Read<long>); 

明らかに、私はこの構文を可能にする18のメソッドに加えて2つのラッパーを書くことを意味しません。構文は重要ではなく、コードの重複が問題です。別の考慮事項は、パフォーマンスです。理想的には、パフォーマンスヒットのいずれか(または多く)はありません。ありがとう。

更新:おそらく重複している他の質問については

。私は彼らの誰もが私の後の特定の一般化に対処していないので、同意しなかったが、1つはかなり近づいた: C# Reading Byte Array最初の答えは、これは18の方法のうちの9つをカバーする。したがって問題の半分が解決されます。私はまだ、さまざまな配列のすべてを読み込む必要があります。

public class FixedFormatParser2 : BinaryReader 
{ 
    public FixedFormatParser2(byte[] input) : base(new MemoryStream(input)) 
    { 
    } 

    public override string ReadString() 
    { 
     //    
    } 

    public double[] ReadDoubleArray() 
    { 
     int size = ReadInt32(); 

     if (size == 0) 
      return null; 

     double[] res = new double[size]; 

     for (int i = 0; i < size; i++) 
      res[i] = ReadDouble(); 

     return res; 
    } 
} 

それぞれのタイプに別々のReadXXXArrayを書き込まないでください。

私はそれに着い最寄り:

public void WriteCountedArray(dynamic[] input) 
    { 
     if (input == null || input.Length == 0) 
      Write((int)0); 
     else 
     { 
      Write(input.Length); 
      foreach (dynamic val in input) 
       Write(val); 
     } 
    } 

これはコンパイルが、それを呼び出すことは面倒かつ高価である:

 using (FixedFormatWriter writer = new FixedFormatWriter()) 
     { 
      double[] array = new double[3]; 
      // ... assign values 
      writer.WriteCountedArray(array.Select(x=>(dynamic)x).ToArray()); 
+2

ようにすることが好きあなたがやっていることをするためには、[この質問は役に立ちます](http://stackoverflow.com/q/1455581/120955)? – StriplingWarrior

+0

StriplingWarrior - 私はあなたの提案を働かせて迷惑をかけました。実際の例へのより良いリンクは、http://stackoverflow.com/questions/2623761/marshal-ptrtostructure-and-back-again-and-generic-solution-for-endianness-swapこのアプローチの問題は、高価で面倒なことに、私はコードの重複を好むでしょう。しかし、はい、それは私が尋ねたことを技術的に行います。 –

答えて

0

私は、私が試したことのないこの

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Data; 
using System.Xml; 
using System.Xml.Serialization; 
using System.IO; 


namespace ConsoleApplication50 
{ 
    class Program 
    { 

     static void Main(string[] args) 
     { 
      new Format(); 

     } 
    } 
    public class Format 
    { 
     public enum TYPES 
     { 
      INT, 
      INT16, 
      LONG 
     } 

     public static List<Format> format = new List<Format>() { 
      new Format() { name = "AccountNumber", _type = TYPES.INT ,numberOfBytes = 4}, 
      new Format() { name = "Age", _type = TYPES.INT16 ,numberOfBytes = 2}, 
      new Format() { name = "AccountNumber", _type = TYPES.LONG ,numberOfBytes = 8} 
     }; 

     public Dictionary<string, object> dict = new Dictionary<string, object>(); 

     public string name { get; set; } 
     public TYPES _type { get; set; } 
     public int numberOfBytes { get; set; } 

     public Format() { } 

     public Format(byte[] contents) 
     { 
      MemoryStream stream = new MemoryStream(contents); 
      BinaryReader reader = new BinaryReader(stream); 

      foreach (Format item in format) 
      { 
       switch (item._type) 
       { 
        case TYPES.INT16 : 
         dict.Add(item.name, reader.ReadInt16()); 
         break; 

        case TYPES.INT: 
         dict.Add(item.name, reader.ReadInt32()); 
         break; 

        case TYPES.LONG: 
         dict.Add(item.name, reader.ReadInt64()); 
         break; 

       } 
      } 
     } 
    } 

} 
関連する問題