2013-01-11 109 views
3

是否可以在一次調用中從二進制文件中讀取結構數組?從二進制文件快速讀取結構數組

例如,我有一個包含頂點十萬文件:

struct Vector3 { float x, y, z; }

我需要C#端口的C++代碼:

Vector3 *verts = new Vector3[num_verts]; 
fread (verts, sizeof(Vector3), num_verts, f); 

回答

5

這裏有一個(幾個)方法:

void Main() 
{ 
    var pts = 
     (from x in Enumerable.Range(0, 10) 
     from y in Enumerable.Range(0, 10) 
     from z in Enumerable.Range(0, 10) 
     select new Vector3(){X = x, Y = y, Z = z}).ToArray(); 

    // write it out... 
    var bigAssByteArray = new byte[Marshal.SizeOf(typeof(Vector3)) * pts.Length]; 
    var pinnedHandle = GCHandle.Alloc(pts, GCHandleType.Pinned);  
    Marshal.Copy(pinnedHandle.AddrOfPinnedObject(), bigAssByteArray, 0, bigAssByteArray.Length); 
    pinnedHandle.Free(); 
    File.WriteAllBytes(@"c:\temp\vectors.out", bigAssByteArray); 

    // ok, read it back... 
    var readBytes = File.ReadAllBytes(@"c:\temp\vectors.out"); 
    var numVectors = readBytes.Length/Marshal.SizeOf(typeof(Vector3)); 
    var readVectors = new Vector3[numVectors]; 
    pinnedHandle = GCHandle.Alloc(readVectors, GCHandleType.Pinned); 
    Marshal.Copy(readBytes, 0, pinnedHandle.AddrOfPinnedObject(), readBytes.Length); 
    pinnedHandle.Free(); 

    var allEqual = 
     pts.Zip(readVectors, 
      (v1,v2) => (v1.X == v2.X) && (v1.Y == v2.Y) && (v1.Z == v2.Z)) 
     .All(p => p); 
    Console.WriteLine("pts == readVectors? {0}", allEqual); 
} 


struct Vector3 
{ 
    public float X; 
    public float Y; 
    public float Z; 
} 
+0

感謝(9多了去了) – Newbee

1

是的,這是可能的,但你必須添加屬性到第e結構,因此您可以精確指定它在內存中的映射方式,以便在結構中沒有填充。

通常,自己轉換數據通常更簡單。絕大多數處理時間將從文件讀取數據,因此轉換數據的開銷很小。例如:

byte[] bytes = File.ReadAllBytes(fileName); 
Vector3[] data = new Vector3[bytes.Length/12]; 
for (var i = 0; i < data.Length; i++) { 
    Vector3 item; 
    item.x = BitConverter.ToSingle(bytes, i * 12); 
    item.y = BitConverter.ToSingle(bytes, i * 12 + 4); 
    item.z = BitConverter.ToSingle(bytes, i * 12 + 8); 
    data[i] = item; 
} 
+0

大致如此,雖然浮動的編組大小爲4,所以你不必擔心改變包裝的尺寸。 – JerKimball