【问题标题】:C#, Write and read images from Binary FileC#,从二进制文件写入和读取图像
【发布时间】:2014-10-19 02:36:38
【问题描述】:

我正在学习 C#,并在 BinaryReader/Writer 上进行堆栈。我如何在这个原因中读/写文件: 我需要将此数据存储到二进制文件中。 (精灵类)

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、大小和转储。加载功能“似乎”几乎“完成”,但我不知道如何为那个“阅读器”编写文件。请显示解决方案。感谢您的提前!

【问题讨论】:

    标签: c# image-processing binaryfiles


    【解决方案1】:

    你的基本问题是你不知道精灵在文件中的位置,直到你写它(除非你遍历数组并计算字节,这是可能的),但你想写索引在精灵之前。您有几个选择:

    首先,为什么要有索引?如果你知道你有多少个精灵,你可以只写那个数字,然后按顺序读取文件,一次一个精灵。这是最简单的:

    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);
            }
        }
    }
    

    另一种选择是先写入精灵并跟踪它们在索引数组中的位置,但在精灵之后写入索引。然后,要读取,您从文件开头读取 sprite 计数,将其乘以 8(long 的大小),然后查找到文件末尾减去那么多。那就是:

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

    【讨论】:

    • 感谢您的建议,先生!这些信息对学习非常有用!
    猜你喜欢
    • 1970-01-01
    • 2021-07-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-07
    • 2015-06-16
    • 1970-01-01
    相关资源
    最近更新 更多