2014-10-19 119 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