2014-10-19 179 views
0

我正在學習C#,並在BinaryReader/Writer上堆疊。如何在這個原因中讀取/寫入文件: 我需要將這些數據存儲到二進制文件中。 (Sprite類)C#,寫入和讀取二進制文件中的圖像

public class Sprite 
{ 
    public Int32 id; //spriteID 
    public Int32 size; //sprite byte size 
    public byte[] dump; //sprite image byte-array 
    public Sprite() 
    { 
     id = 0; 
     size = 0; 
     dump = null; 
    } 
} 

我對這個功能得到了精靈的數據:

public Sprite createSprite(Image image, System.Drawing.Imaging.ImageFormat format) 
    { 
     using (MemoryStream ms = new MemoryStream()) 
     { 
     Sprite tmpSpr = new Sprite(); 
     image.Save(ms, format); 
     tmpSpr.dump = ms.ToArray(); 
     tmpSpr.size = tmpSpr.Length; 
     tmpSpr.id = 1; //just for example 
     return tmpSpr; 
     } 
    } 

但我堆在解決這個問題:

public static bool save(string filename) 
    { 
     FileStream fileStream = new FileStream(filename, FileMode.Create); 
     MemoryStream ms = new MemoryStream(); 
     BinaryWriter wr = new BinaryWriter(ms); 
     //How i am should write a sprites here? 
    } 

這裏未完成讀取功能。也可以閱讀。

public static bool load(string filename, ref Dictionary<UInt32, Sprite> sprites) 
{ 
    FileStream fileStream = new FileStream(filename, FileMode.Open); 
     try 
     { 
      using (BinaryReader reader = new BinaryReader(fileStream)) 
      { 
       UInt32 totalSprites = reader.ReadUInt32(); //total sprites in file 
       //something like that? 
       List<UInt32> spriteIndexes = new List<UInt32>(); 
       for (uint i = 0; i < totalSprites; ++i) 
       { 
        UInt32 index = reader.ReadUInt32(); 
        spriteIndexes.Add(index); 
       } 
       UInt32 id = 1; 
       foreach (UInt32 element in spriteIndexes) 
       { 
        //i am not sure here =(
        reader.BaseStream.Seek(element, SeekOrigin.Begin); 
        UInt32 size = reader.ReadUInt32(); 

        Sprite sprite; 
        if (sprites.TryGetValue(id, out sprite)) 
        { 
         if (sprite != null && size > 0) 
         { 
          if (sprite.size > 0) 
          { 
           //generate warning 
          } 
          else 
          { 
           sprite.id = id; 
           sprite.size = size; 
           sprite.dump = reader.ReadBytes(size); 

           sprites[id] = sprite; 
          } 
         } 
        } 
        else 
        { 
         //i am not shure here too. 
         reader.BaseStream.Seek(size, SeekOrigin.Current); 
        } 

        ++id; 
       } 
      } 
     } 
     finally 
     { 
      fileStream.Close(); 
     } 
     return true; 
} 

Sprite文件應該有一個totalSprites參數,以及所有sprite的列表,以及它們的id,size,dump。加載函數「似乎」幾乎「完成」,但我沒有想法,如何爲該「讀者」編寫文件。請展示解決方案。感謝您的提前!

回答

2

你的基本問題是你不知道精靈在文件中的位置是什麼,直到你寫它(除非你通過數組並計算字節數,這是可能的),但是你想寫指數在精靈之前。你有幾個選擇:

首先,爲什麼有一個索引呢?如果你知道你有多少個精靈,你可以只寫這個數字,然後按順序讀一個精靈,一次一個精靈。這是最簡單的:

using (var fs = File.OpenWrite(filename)) 
{ 
    using (var writer = new BinaryWriter(fs)) 
    { 
     // write sprite count 
     writer.Write(spriteList.Count); 
     // and write each sprite 
     foreach (var s in spriteList) 
     { 
      writer.Write(sprite.id); 
      writer.Write(sprite.size); 
      writer.Write(sprite.dump); 
     } 
    } 
} 

閱讀正好相反:讀取計數,然後讀取許多精靈。除非你想要讀取第五個精靈,否則不需要索引,例如,無需讀取前四個精靈。

如果你確實需要索引,你可以爲它編寫一個佔位符,然後編寫精靈,跟蹤它們的位置,然後回溯到文件的開頭並編寫真實索引。像這樣:

var index = new List<long>(spriteList.Count); 
using (var fs = File.OpenWrite(filename)) 
{ 
    using (var writer = new BinaryWriter(fs)) 
    { 
     // write sprite count 
     writer.Write(spriteList.Count); 

     var indexPos = writer.BaseStream.Position; 

     // write index placeholder 
     for (var i = 0; i < spriteList.Count; ++i) 
     { 
      writer.Write(0L); 
     } 

     // and write each sprite 
     for (var i = 0; i < spriteList.Count ++i) 
     { 
      // save current position 
      writer.Flush(); 
      index[i] = writer.BaseStream.Position; 

      writer.Write(sprite.id); 
      writer.Write(sprite.size); 
      writer.Write(sprite.dump); 
     } 

     // Seek back to the index position 
     writer.Flush(); 
     writer.BaseStream.Position = indexPos; 

     // and write the real index 
     foreach (var pos in index) 
     { 
      writer.Write(pos); 
     } 
    } 
} 

另一種方法是先寫精靈和跟蹤其索引陣列如上面位置的,但經過精靈寫入索引。然後,讀取文件開頭的精靈數,然後乘以8(long的大小),然後尋找文件末尾減去那麼多。那就是:

var spriteCount = reader.ReadInt32(); 
long indexSize = spriteCount * 8; 
reader.BaseStream.Seek(-indexSize, SeekOrigin.End); 
// now read the index of spriteCount values 
+0

謝謝您的建議先生!這些信息對學習非常有用! – 2014-10-19 03:19:08